@@ -10,8 +10,6 @@ import (
1010"net"
1111"net/netip"
1212"os"
13- "slices"
14- "strings"
1513"sync"
1614
1715"github.com/vishvananda/netlink"
@@ -32,59 +30,19 @@ var (
3230
3331// NetlinkRouter implements Router using Linux's netlink subsystem.
3432type NetlinkRouter struct {
35- extLink netlink.Link
33+ extLink netlink.Link
34+ extIPv6Prefix netip.Prefix
35+
3636tunDev tun.Device
3737tunLink netlink.Link
3838
39- extAddr netip.Addr
40- extPrefixes []netip.Prefix
41- ipt utiliptables.Interface
39+ ipt utiliptables.Interface
4240
4341mux * connection.MuxedConn
4442
4543closeOnce sync.Once
4644}
4745
48- func extPrefixes (link netlink.Link ) (netip.Addr , []netip.Prefix , error ) {
49- slog .Info ("Checking link" , slog .String ("name" , link .Attrs ().Name ))
50-
51- addrs , err := netlink .AddrList (link , netlink .FAMILY_V6 )
52- if err != nil {
53- return netip.Addr {}, nil , fmt .Errorf ("failed to get addresses for link: %w" , err )
54- }
55-
56- var extAddr netip.Addr
57- var prefixes []netip.Prefix
58- for _ , addr := range addrs {
59- slog .Debug ("Checking address" , slog .String ("addr" , addr .String ()))
60- // Skip loopback addresses
61- ip , ok := netip .AddrFromSlice (addr .IP )
62- if ! ok {
63- slog .Warn ("Failed to convert IP address" , slog .String ("ip" , addr .IP .String ()))
64- continue
65- }
66- if ! ip .Is6 () {
67- slog .Warn ("Skipping non-IPv6 address" , slog .String ("ip" , addr .IP .String ()))
68- continue
69- }
70- if ! ip .IsGlobalUnicast () { // Skip non-global unicast addresses.
71- slog .Debug ("Skipping non-global unicast address" , slog .String ("ip" , addr .IP .String ()))
72- continue
73- }
74-
75- slog .Info ("Found IPv6 address" , slog .String ("ip" , addr .IP .String ()), slog .String ("mask" , addr .Mask .String ()))
76-
77- if ! extAddr .IsValid () {
78- extAddr = ip
79- }
80-
81- bits , _ := addr .Mask .Size ()
82- prefixes = append (prefixes , netip .PrefixFrom (ip , bits ))
83- }
84-
85- return extAddr , prefixes , nil
86- }
87-
8846// NewNetlinkRouter creates a new netlink-based tunnel router.
8947func NewNetlinkRouter (opts ... Option ) (* NetlinkRouter , error ) {
9048options := defaultOptions ()
@@ -96,10 +54,6 @@ func NewNetlinkRouter(opts ...Option) (*NetlinkRouter, error) {
9654if err != nil {
9755return nil , fmt .Errorf ("failed to get external interface: %w" , err )
9856}
99- extAddr , lrs , err := extPrefixes (extLink )
100- if err != nil {
101- return nil , fmt .Errorf ("failed to get local routes: %w" , err )
102- }
10357
10458tunDev , err := tun .CreateTUN (options .tunIfaceName , netstack .IPv6MinMTU )
10559if err != nil {
@@ -157,9 +111,7 @@ func NewNetlinkRouter(opts ...Option) (*NetlinkRouter, error) {
157111tunDev : tunDev ,
158112tunLink : tunLink ,
159113
160- extAddr : extAddr ,
161- extPrefixes : lrs ,
162- ipt : utiliptables .New (utilexec .New (), utiliptables .ProtocolIPv6 ),
114+ ipt : utiliptables .New (utilexec .New (), utiliptables .ProtocolIPv6 ),
163115
164116mux : connection .NewMuxedConn (),
165117}, nil
@@ -181,14 +133,12 @@ func (r *NetlinkRouter) setupDNAT() error {
181133extName := r .extLink .Attrs ().Name
182134tunName := r .tunLink .Attrs ().Name
183135
184- // Setup jump rule to our custom chain.
185- var dsts []string
186- for _ , prefix := range r .extPrefixes {
187- dsts = append (dsts , prefix .Addr ().String ())
188- }
189- slices .Sort (dsts )
190- slog .Info ("Setting up jump rule" , slog .String ("ext_iface" , extName ), slog .String ("tun_iface" , tunName ), slog .String ("dsts" , strings .Join (dsts , "," )))
191- jRuleSpec := []string {"-d" , strings .Join (dsts , "," ), "-i" , extName , "-j" , string (ChainA3yTunRules )}
136+ slog .Info ("Setting up jump rule" ,
137+ slog .String ("ext_iface" , extName ),
138+ slog .String ("ext_addr" , r .extIPv6Prefix .Addr ().String ()))
139+
140+ // Traffic arriving at the designated external interface will be processed by the A3Y-TUN-RULES chain.
141+ jRuleSpec := []string {"-d" , r .extIPv6Prefix .Addr ().String (), "-i" , extName , "-j" , string (ChainA3yTunRules )}
192142if _ , err := r .ipt .EnsureRule (utiliptables .Append , utiliptables .TableNAT , utiliptables .ChainPrerouting , jRuleSpec ... ); err != nil {
193143return fmt .Errorf ("failed to ensure jump rule: %w" , err )
194144}
0 commit comments