@@ -11,6 +11,7 @@ import (
1111"net/netip"
1212"os"
1313"sync"
14+ "syscall"
1415
1516"github.com/vishvananda/netlink"
1617"golang.org/x/sync/errgroup"
@@ -107,7 +108,7 @@ func newClientNetlinkRouter(opts ...Option) (*ClientNetlinkRouter, error) {
107108IP : ip .AsSlice (),
108109Mask : mask ,
109110},
110- }); err != nil {
111+ }); err != nil && err != syscall . EEXIST {
111112tunDev .Close ()
112113return nil , fmt .Errorf ("failed to add address to TUN interface: %w" , err )
113114}
@@ -134,6 +135,17 @@ func newClientNetlinkRouter(opts ...Option) (*ClientNetlinkRouter, error) {
134135func (r * ClientNetlinkRouter ) setupIptables () error {
135136tunName := r .tunLink .Attrs ().Name
136137
138+ // SNAT traffic comming into tunnel to overlay prefix.
139+ for _ , p := range r .options .localAddresses {
140+ if p .Addr ().Is4 () {
141+ r .iptV4 .EnsureRule (utiliptables .Prepend , utiliptables .TableNAT , utiliptables .ChainPostrouting ,
142+ "-o" , tunName , "-j" , "SNAT" , "--to-source" , p .Addr ().String ())
143+ } else {
144+ r .iptV6 .EnsureRule (utiliptables .Prepend , utiliptables .TableNAT , utiliptables .ChainPostrouting ,
145+ "-o" , tunName , "-j" , "SNAT" , "--to-source" , p .Addr ().String ())
146+ }
147+ }
148+
137149// TODO: Set conntrack rules for route switching.
138150// # Ensure connections maintain their original path
139151// iptables -A OUTPUT -o tun0 -m conntrack --ctorigdst tun0 -j ACCEPT
0 commit comments