Skip to content

Commit

Permalink
chore: listening tcp together for dns server (#1792)
Browse files Browse the repository at this point in the history
  • Loading branch information
wwqgtxx committed Jan 16, 2025
1 parent c7661d7 commit c99c71a
Show file tree
Hide file tree
Showing 15 changed files with 140 additions and 102 deletions.
27 changes: 25 additions & 2 deletions adapter/inbound/listen.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func MPTCP() bool {
return getMultiPathTCP(&lc.ListenConfig)
}

func ListenContext(ctx context.Context, network, address string) (net.Listener, error) {
func preResolve(network, address string) (string, error) {
switch network { // like net.Resolver.internetAddrList but filter domain to avoid call net.Resolver.lookupIPAddr
case "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6", "ip", "ip4", "ip6":
if host, port, err := net.SplitHostPort(address); err == nil {
Expand All @@ -59,11 +59,19 @@ func ListenContext(ctx context.Context, network, address string) (net.Listener,
break
default:
if _, err := netip.ParseAddr(host); err != nil { // not ip
return nil, fmt.Errorf("invalid network address: %s", address)
return "", fmt.Errorf("invalid network address: %s", address)
}
}
}
}
return address, nil
}

func ListenContext(ctx context.Context, network, address string) (net.Listener, error) {
address, err := preResolve(network, address)
if err != nil {
return nil, err
}

mutex.RLock()
defer mutex.RUnlock()
Expand All @@ -74,6 +82,21 @@ func Listen(network, address string) (net.Listener, error) {
return ListenContext(context.Background(), network, address)
}

func ListenPacketContext(ctx context.Context, network, address string) (net.PacketConn, error) {
address, err := preResolve(network, address)
if err != nil {
return nil, err
}

mutex.RLock()
defer mutex.RUnlock()
return lc.ListenPacket(ctx, network, address)
}

func ListenPacket(network, address string) (net.PacketConn, error) {
return ListenPacketContext(context.Background(), network, address)
}

func init() {
keepalive.SetDisableKeepAliveCallback.Register(func(b bool) {
mutex.Lock()
Expand Down
30 changes: 30 additions & 0 deletions common/sockopt/reuse_common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package sockopt

import (
"net"
"syscall"
)

func RawConnReuseaddr(rc syscall.RawConn) (err error) {
var innerErr error
err = rc.Control(func(fd uintptr) {
innerErr = reuseControl(fd)
})

if innerErr != nil {
err = innerErr
}
return
}

func UDPReuseaddr(c net.PacketConn) error {
if c, ok := c.(syscall.Conn); ok {
rc, err := c.SyscallConn()
if err != nil {
return err
}

return RawConnReuseaddr(rc)
}
return nil
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
//go:build !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !windows

package dialer
package sockopt

import (
"net"
)

func addrReuseToListenConfig(*net.ListenConfig) {}
func reuseControl(fd uintptr) error { return nil }
22 changes: 22 additions & 0 deletions common/sockopt/reuse_unix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris

package sockopt

import (
"golang.org/x/sys/unix"
)

func reuseControl(fd uintptr) error {
e1 := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEADDR, 1)
e2 := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1)

if e1 != nil {
return e1
}

if e2 != nil {
return e2
}

return nil
}
9 changes: 9 additions & 0 deletions common/sockopt/reuse_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package sockopt

import (
"golang.org/x/sys/windows"
)

func reuseControl(fd uintptr) error {
return windows.SetsockoptInt(windows.Handle(fd), windows.SOL_SOCKET, windows.SO_REUSEADDR, 1)
}
19 changes: 0 additions & 19 deletions common/sockopt/reuseaddr_linux.go

This file was deleted.

11 changes: 0 additions & 11 deletions common/sockopt/reuseaddr_other.go

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,11 @@ import (
"net"
"syscall"

"golang.org/x/sys/windows"
"github.com/metacubex/mihomo/common/sockopt"
)

func addrReuseToListenConfig(lc *net.ListenConfig) {
addControlToListenConfig(lc, func(ctx context.Context, network, address string, c syscall.RawConn) error {
return c.Control(func(fd uintptr) {
windows.SetsockoptInt(windows.Handle(fd), windows.SOL_SOCKET, windows.SO_REUSEADDR, 1)
})
return sockopt.RawConnReuseaddr(c)
})
}
20 changes: 0 additions & 20 deletions component/dialer/reuse_unix.go

This file was deleted.

66 changes: 40 additions & 26 deletions dns/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"net"

"github.com/metacubex/mihomo/adapter/inbound"
"github.com/metacubex/mihomo/common/sockopt"
"github.com/metacubex/mihomo/context"
"github.com/metacubex/mihomo/log"
Expand All @@ -20,8 +21,9 @@ var (
)

type Server struct {
*D.Server
handler handler
handler handler
tcpServer *D.Server
udpServer *D.Server
}

// ServeDNS implement D.Handler ServeDNS
Expand Down Expand Up @@ -55,12 +57,19 @@ func ReCreateServer(addr string, resolver *Resolver, mapper *ResolverEnhancer) {
return
}

if server.Server != nil {
server.Shutdown()
server = &Server{}
address = ""
if server.tcpServer != nil {
_ = server.tcpServer.Shutdown()
server.tcpServer = nil
}

if server.udpServer != nil {
_ = server.udpServer.Shutdown()
server.udpServer = nil
}

server.handler = nil
address = ""

if addr == "" {
return
}
Expand All @@ -77,31 +86,36 @@ func ReCreateServer(addr string, resolver *Resolver, mapper *ResolverEnhancer) {
return
}

udpAddr, err := net.ResolveUDPAddr("udp", addr)
if err != nil {
return
}

p, err := net.ListenUDP("udp", udpAddr)
if err != nil {
return
}

err = sockopt.UDPReuseaddr(p)
if err != nil {
log.Warnln("Failed to Reuse UDP Address: %s", err)

err = nil
}

address = addr
handler := NewHandler(resolver, mapper)
server = &Server{handler: handler}
server.Server = &D.Server{Addr: addr, PacketConn: p, Handler: server}

go func() {
server.ActivateAndServe()
p, err := inbound.ListenPacket("udp", addr)
if err != nil {
log.Errorln("Start DNS server(UDP) error: %s", err.Error())
return
}

if err := sockopt.UDPReuseaddr(p); err != nil {
log.Warnln("Failed to Reuse UDP Address: %s", err)
}

log.Infoln("DNS server(UDP) listening at: %s", p.LocalAddr().String())
server.udpServer = &D.Server{Addr: addr, PacketConn: p, Handler: server}
_ = server.udpServer.ActivateAndServe()
}()

go func() {
l, err := inbound.Listen("tcp", addr)
if err != nil {
log.Errorln("Start DNS server(TCP) error: %s", err.Error())
return
}

log.Infoln("DNS server(TCP) listening at: %s", l.Addr().String())
server.tcpServer = &D.Server{Addr: addr, Listener: l, Handler: server}
_ = server.tcpServer.ActivateAndServe()
}()

log.Infoln("DNS server listening at: %s", p.LocalAddr().String())
}
5 changes: 2 additions & 3 deletions listener/shadowsocks/udp.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,12 @@ type UDPListener struct {
}

func NewUDP(addr string, pickCipher core.Cipher, tunnel C.Tunnel, additions ...inbound.Addition) (*UDPListener, error) {
l, err := net.ListenPacket("udp", addr)
l, err := inbound.ListenPacket("udp", addr)
if err != nil {
return nil, err
}

err = sockopt.UDPReuseaddr(l.(*net.UDPConn))
if err != nil {
if err := sockopt.UDPReuseaddr(l); err != nil {
log.Warnln("Failed to Reuse UDP Address: %s", err)
}

Expand Down
5 changes: 2 additions & 3 deletions listener/sing_hysteria2/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,13 +140,12 @@ func New(config LC.Hysteria2Server, tunnel C.Tunnel, additions ...inbound.Additi
_service := *service
service := &_service // make a copy

ul, err := net.ListenPacket("udp", addr)
ul, err := inbound.ListenPacket("udp", addr)
if err != nil {
return nil, err
}

err = sockopt.UDPReuseaddr(ul.(*net.UDPConn))
if err != nil {
if err := sockopt.UDPReuseaddr(ul); err != nil {
log.Warnln("Failed to Reuse UDP Address: %s", err)
}

Expand Down
5 changes: 2 additions & 3 deletions listener/sing_shadowsocks/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,12 @@ func New(config LC.ShadowsocksServer, tunnel C.Tunnel, additions ...inbound.Addi

if config.Udp {
//UDP
ul, err := net.ListenPacket("udp", addr)
ul, err := inbound.ListenPacket("udp", addr)
if err != nil {
return nil, err
}

err = sockopt.UDPReuseaddr(ul.(*net.UDPConn))
if err != nil {
if err := sockopt.UDPReuseaddr(ul); err != nil {
log.Warnln("Failed to Reuse UDP Address: %s", err)
}

Expand Down
4 changes: 2 additions & 2 deletions listener/socks/udp.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@ func NewUDP(addr string, tunnel C.Tunnel, additions ...inbound.Addition) (*UDPLi
inbound.WithSpecialRules(""),
}
}
l, err := net.ListenPacket("udp", addr)
l, err := inbound.ListenPacket("udp", addr)
if err != nil {
return nil, err
}

if err := sockopt.UDPReuseaddr(l.(*net.UDPConn)); err != nil {
if err := sockopt.UDPReuseaddr(l); err != nil {
log.Warnln("Failed to Reuse UDP Address: %s", err)
}

Expand Down
5 changes: 2 additions & 3 deletions listener/tuic/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,13 +152,12 @@ func New(config LC.TuicServer, tunnel C.Tunnel, additions ...inbound.Addition) (
for _, addr := range strings.Split(config.Listen, ",") {
addr := addr

ul, err := net.ListenPacket("udp", addr)
ul, err := inbound.ListenPacket("udp", addr)
if err != nil {
return nil, err
}

err = sockopt.UDPReuseaddr(ul.(*net.UDPConn))
if err != nil {
if err := sockopt.UDPReuseaddr(ul); err != nil {
log.Warnln("Failed to Reuse UDP Address: %s", err)
}

Expand Down

0 comments on commit c99c71a

Please sign in to comment.