@@ -192,7 +192,6 @@ func NewEndpoint(ctx context.Context, id string, d connector, pm *atomic.Pointer
192192
193193type StdNetEndpoint struct {
194194 netip.AddrPort
195- addr * net.UDPAddr
196195}
197196
198197var invalidStdNetEndpoint = StdNetEndpoint {}
@@ -222,23 +221,45 @@ func (e *StdNetBind) ParseEndpoint(s string) (conn.Endpoint, error) {
222221 return nil , err
223222 }
224223
224+ ogep , _ := netip .ParseAddrPort (s )
225+ is6 := ogep .Addr ().Is6 ()
226+
227+ var ipport , altipport netip.AddrPort
228+
225229 all := d .Addrs ()
226- // do what tailscale does, and share a preferred endpoint regardless of "s"
230+ // do what tailscale does, and share a preferred endpoint regardless of "s"?
227231 // github.com/tailscale/tailscale/blob/3a6d3f1a5b7/wgengine/magicsock/magicsock.go#L2568
228- ipport := d .PreferredAddr ()
232+ ipp4 , ipp6 := d .PreferredAddr2 ()
233+ if is6 && ipp6 .IsValid () {
234+ // in cases where dialers.Use4() and dialers.Use6 return true, but only v6 route
235+ // may in fact exist (v4 is over only DNS64 / NAT64), prefer v6 instead
236+ ipport = ipp6
237+ altipport = ipp4
238+ } else {
239+ ipport = ipp4
240+ altipport = ipp6
241+ }
229242 if ! ipport .IsValid () || ipport .Addr ().IsUnspecified () {
230- log .E ("wg: bind: parse: %s invalid endpoint; chosen(%v ) => in(%s) => out(%s, %s)" , e .id , ipport , s , d .Names (), d . Addrs () )
243+ log .E ("wg: bind: parse: %s invalid endpoint; (chosen: %v / alt: %v ) => in(%s) => out(%s, %s)" , e .id , ipport , altipport , s , d .Names (), all )
231244 // erroring out from here prevents PostConfig (handshake for this peer endpoint will always be zero)
232245 // github.com/WireGuard/wireguard-go/blob/12269c276173/device/uapi.go#L183
233246 return nil , errInvalidEndpoint
234247 }
235248
236249 e .sendAddr .Store (& ipport )
237250
238- log .I ("wg: bind: %s new shared endpoint for %s %v [among: %s]" , e .id , s , ipport , all )
251+ log .I ("wg: bind: %s new shared endpoint for %s %v [alt: %s / among: %s]" , e .id , s , ipport , altipport , all )
239252
240253 // todo: add stdnetendpoint to s.eps
241- return StdNetEndpoint {ipport , udpaddr (ipport )}, nil
254+ return StdNetEndpoint {ipport }, nil
255+ }
256+
257+ func (e StdNetEndpoint ) get () netip.AddrPort {
258+ return e .AddrPort
259+ }
260+
261+ func (e StdNetEndpoint ) get2 () * net.UDPAddr {
262+ return udpaddr (e .get ())
242263}
243264
244265func (StdNetEndpoint ) ClearSrc () {} // not supported
@@ -251,9 +272,9 @@ func (e StdNetEndpoint) SrcIP() netip.Addr {
251272 return netip.Addr {} // not supported
252273}
253274
254- func (e StdNetEndpoint ) DstToBytes () []byte {
255- b , _ : = e .MarshalBinary ()
256- return b
275+ func (e StdNetEndpoint ) DstToBytes () ( b []byte ) {
276+ b , _ = e .MarshalBinary ()
277+ return
257278}
258279
259280func (e StdNetEndpoint ) DstToString () string {
@@ -599,7 +620,7 @@ func (s *StdNetBind) Send(buf [][]byte, peer conn.Endpoint) (err error) {
599620 log .E ("wg: bind: send: %s wrong endpoint type: %T" , s .id , peer )
600621 return conn .ErrWrongEndpointType
601622 }
602- dstIpp := ep .AddrPort
623+ dstIpp := ep .get ()
603624
604625 s .mu .RLock ()
605626 blackhole := s .blackhole4
@@ -653,7 +674,7 @@ func (s *StdNetBind) Send(buf [][]byte, peer conn.Endpoint) (err error) {
653674 }
654675 }
655676
656- n , serr := uc .WriteTo (data , ep .addr )
677+ n , serr := uc .WriteTo (data , ep .get2 () )
657678
658679 anyTimedout = anyTimedout || timedout (serr )
659680 if serr != nil { // TODO: && discard timeouts?
@@ -678,7 +699,7 @@ func (s *StdNetBind) Send(buf [][]byte, peer conn.Endpoint) (err error) {
678699// github.com/WireGuard/wireguard-go/blob/19ac233cc6/wireguard/device/send.go#L96
679700// github.com/GFW-knocker/wireguard/blob/8bd9f582b4/device/send.go#L98
680701func (s * StdNetBind ) flood (fd int , c net.PacketConn , dst StdNetEndpoint , why floodkind ) (int , error ) {
681- return s .floodBa .DoIt (dst .AddrPort , func () (int , error ) {
702+ return s .floodBa .DoIt (dst .get () , func () (int , error ) {
682703 hdrlen := len (wgheader )
683704 hdr := make ([]byte , hdrlen )
684705 copy (hdr , wgheader )
@@ -701,7 +722,7 @@ func (s *StdNetBind) flood(fd int, c net.PacketConn, dst StdNetEndpoint, why flo
701722 _ , _ = rand .Read (pkt [hdrlen :sz ])
702723 copy (pkt [0 :], hdr )
703724
704- sent , err := c .WriteTo (pkt , dst .addr )
725+ sent , err := c .WriteTo (pkt , dst .get2 () )
705726
706727 expectedsent [i ] = hdrlen + int (sz )
707728 n += sent
@@ -797,12 +818,12 @@ func (s *StdNetBind) asEndpoint(x net.Addr) (int, conn.Endpoint) {
797818
798819 if tcp , ok := x .(* net.TCPAddr ); ok {
799820 ipp := tcp .AddrPort ()
800- ep = StdNetEndpoint {ipp , udpaddr ( ipp ) }
821+ ep = StdNetEndpoint {ipp }
801822 } else if udp , ok := x .(* net.UDPAddr ); ok {
802823 ipp := udp .AddrPort ()
803- ep = StdNetEndpoint {ipp , udpaddr ( ipp ) } // copy udp addr
824+ ep = StdNetEndpoint {ipp } // copy udp addr
804825 } else if ipp , err := netip .ParseAddrPort (ap ); err == nil {
805- ep = StdNetEndpoint {ipp , udpaddr ( ipp ) }
826+ ep = StdNetEndpoint {ipp }
806827 }
807828 if len (s .eps ) >= maxEpsSize { // evict all; entries repopulate as packets arrive
808829 log .W ("wg: bind: %s eps full; clearing %d" , s .id , sz )
0 commit comments