Skip to content

Commit

Permalink
fix: don't ignore bind6 error when udp's target is ipv6 address
Browse files Browse the repository at this point in the history
  • Loading branch information
wwqgtxx committed Apr 10, 2024
1 parent cff7df1 commit 16fadd2
Show file tree
Hide file tree
Showing 7 changed files with 22 additions and 23 deletions.
3 changes: 2 additions & 1 deletion component/dhcp/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package dhcp
import (
"context"
"net"
"net/netip"
"runtime"

"github.com/metacubex/mihomo/component/dialer"
Expand All @@ -24,5 +25,5 @@ func ListenDHCPClient(ctx context.Context, ifaceName string) (net.PacketConn, er
options = append(options, dialer.WithFallbackBind(true))
}

return dialer.ListenPacket(ctx, "udp4", listenAddr, options...)
return dialer.ListenPacket(ctx, "udp4", listenAddr, netip.AddrPortFrom(netip.AddrFrom4([4]byte{255, 255, 255, 255}), 67), options...)
}
2 changes: 1 addition & 1 deletion component/dialer/bind.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func fallbackBindIfaceToDialer(ifaceName string, dialer *net.Dialer, network str
return nil
}

func fallbackBindIfaceToListenConfig(ifaceName string, _ *net.ListenConfig, network, address string) (string, error) {
func fallbackBindIfaceToListenConfig(ifaceName string, _ *net.ListenConfig, network, address string, rAddrPort netip.AddrPort) (string, error) {
_, port, err := net.SplitHostPort(address)
if err != nil {
port = "0"
Expand Down
2 changes: 1 addition & 1 deletion component/dialer/bind_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func bindIfaceToDialer(ifaceName string, dialer *net.Dialer, _ string, _ netip.A
return nil
}

func bindIfaceToListenConfig(ifaceName string, lc *net.ListenConfig, _, address string) (string, error) {
func bindIfaceToListenConfig(ifaceName string, lc *net.ListenConfig, _, address string, rAddrPort netip.AddrPort) (string, error) {
ifaceObj, err := iface.ResolveInterface(ifaceName)
if err != nil {
return "", err
Expand Down
2 changes: 1 addition & 1 deletion component/dialer/bind_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func bindIfaceToDialer(ifaceName string, dialer *net.Dialer, _ string, _ netip.A
return nil
}

func bindIfaceToListenConfig(ifaceName string, lc *net.ListenConfig, _, address string) (string, error) {
func bindIfaceToListenConfig(ifaceName string, lc *net.ListenConfig, _, address string, rAddrPort netip.AddrPort) (string, error) {
addControlToListenConfig(lc, bindControl(ifaceName))

return address, nil
Expand Down
4 changes: 2 additions & 2 deletions component/dialer/bind_others.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ func bindIfaceToDialer(ifaceName string, dialer *net.Dialer, network string, des
return fallbackBindIfaceToDialer(ifaceName, dialer, network, destination)
}

func bindIfaceToListenConfig(ifaceName string, lc *net.ListenConfig, network, address string) (string, error) {
return fallbackBindIfaceToListenConfig(ifaceName, lc, network, address)
func bindIfaceToListenConfig(ifaceName string, lc *net.ListenConfig, network, address string, rAddrPort netip.AddrPort) (string, error) {
return fallbackBindIfaceToListenConfig(ifaceName, lc, network, address, rAddrPort)
}

func ParseNetwork(network string, addr netip.Addr) string {
Expand Down
12 changes: 6 additions & 6 deletions component/dialer/bind_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func bind6(handle syscall.Handle, ifaceIdx int) error {
return err
}

func bindControl(ifaceIdx int) controlFn {
func bindControl(ifaceIdx int, rAddrPort netip.AddrPort) controlFn {
return func(ctx context.Context, network, address string, c syscall.RawConn) (err error) {
addrPort, err := netip.ParseAddrPort(address)
if err == nil && !addrPort.Addr().IsGlobalUnicast() {
Expand All @@ -55,7 +55,7 @@ func bindControl(ifaceIdx int) controlFn {
innerErr = bind4err
case "udp6":
// golang will set network to udp6 when listenUDP on wildcard ip (eg: ":0", "")
if (!addrPort.Addr().IsValid() || addrPort.Addr().IsUnspecified()) && bind6err != nil {
if (!addrPort.Addr().IsValid() || addrPort.Addr().IsUnspecified()) && bind6err != nil && rAddrPort.Addr().Unmap().Is4() {
// try bind ipv6, if failed, ignore. it's a workaround for windows disable interface ipv6
if bind4err != nil {
innerErr = fmt.Errorf("%w (%s)", bind6err, bind4err)
Expand All @@ -76,23 +76,23 @@ func bindControl(ifaceIdx int) controlFn {
}
}

func bindIfaceToDialer(ifaceName string, dialer *net.Dialer, _ string, _ netip.Addr) error {
func bindIfaceToDialer(ifaceName string, dialer *net.Dialer, _ string, destination netip.Addr) error {
ifaceObj, err := iface.ResolveInterface(ifaceName)
if err != nil {
return err
}

addControlToDialer(dialer, bindControl(ifaceObj.Index))
addControlToDialer(dialer, bindControl(ifaceObj.Index, netip.AddrPortFrom(destination, 0)))
return nil
}

func bindIfaceToListenConfig(ifaceName string, lc *net.ListenConfig, _, address string) (string, error) {
func bindIfaceToListenConfig(ifaceName string, lc *net.ListenConfig, _, address string, rAddrPort netip.AddrPort) (string, error) {
ifaceObj, err := iface.ResolveInterface(ifaceName)
if err != nil {
return "", err
}

addControlToListenConfig(lc, bindControl(ifaceObj.Index))
addControlToListenConfig(lc, bindControl(ifaceObj.Index, rAddrPort))
return address, nil
}

Expand Down
20 changes: 9 additions & 11 deletions component/dialer/dialer.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func DialContext(ctx context.Context, network, address string, options ...Option
}
}

func ListenPacket(ctx context.Context, network, address string, options ...Option) (net.PacketConn, error) {
func ListenPacket(ctx context.Context, network, address string, rAddrPort netip.AddrPort, options ...Option) (net.PacketConn, error) {
if features.CMFA && DefaultSocketHook != nil {
return listenPacketHooked(ctx, network, address)
}
Expand All @@ -91,7 +91,7 @@ func ListenPacket(ctx context.Context, network, address string, options ...Optio
if cfg.fallbackBind {
bind = fallbackBindIfaceToListenConfig
}
addr, err := bind(cfg.interfaceName, lc, network, address)
addr, err := bind(cfg.interfaceName, lc, network, address, rAddrPort)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -133,11 +133,9 @@ func dialContext(ctx context.Context, network string, destination netip.Addr, po

var address string
if IP4PEnable {
NewDestination, NewPort := lookupIP4P(destination.String(), port)
address = net.JoinHostPort(NewDestination, NewPort)
} else {
address = net.JoinHostPort(destination.String(), port)
destination, port = lookupIP4P(destination, port)
}
address = net.JoinHostPort(destination.String(), port)

netDialer := opt.netDialer
switch netDialer.(type) {
Expand Down Expand Up @@ -385,7 +383,7 @@ func (d Dialer) ListenPacket(ctx context.Context, network, address string, rAddr
// avoid "The requested address is not valid in its context."
opt = WithInterface("")
}
return ListenPacket(ctx, ParseNetwork(network, rAddrPort.Addr()), address, opt)
return ListenPacket(ctx, ParseNetwork(network, rAddrPort.Addr()), address, rAddrPort, opt)
}

func NewDialer(options ...Option) Dialer {
Expand All @@ -399,13 +397,13 @@ func GetIP4PEnable(enableIP4PConvert bool) {

// kanged from https://github.com/heiher/frp/blob/ip4p/client/ip4p.go

func lookupIP4P(addr string, port string) (string, string) {
ip := net.ParseIP(addr)
func lookupIP4P(addr netip.Addr, port string) (netip.Addr, string) {
ip := addr.AsSlice()
if ip[0] == 0x20 && ip[1] == 0x01 &&
ip[2] == 0x00 && ip[3] == 0x00 {
addr = net.IPv4(ip[12], ip[13], ip[14], ip[15]).String()
addr = netip.AddrFrom4([4]byte{ip[12], ip[13], ip[14], ip[15]})
port = strconv.Itoa(int(ip[10])<<8 + int(ip[11]))
log.Debugln("Convert IP4P address %s to %s", ip, net.JoinHostPort(addr, port))
log.Debugln("Convert IP4P address %s to %s", ip, net.JoinHostPort(addr.String(), port))
return addr, port
}
return addr, port
Expand Down

0 comments on commit 16fadd2

Please sign in to comment.