mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2025-09-19 20:15:59 +08:00
chore: listening tcp together for dns server (#1792)
This commit is contained in:
@ -43,7 +43,7 @@ func MPTCP() bool {
|
|||||||
return getMultiPathTCP(&lc.ListenConfig)
|
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
|
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":
|
case "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6", "ip", "ip4", "ip6":
|
||||||
if host, port, err := net.SplitHostPort(address); err == nil {
|
if host, port, err := net.SplitHostPort(address); err == nil {
|
||||||
@ -59,11 +59,19 @@ func ListenContext(ctx context.Context, network, address string) (net.Listener,
|
|||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
if _, err := netip.ParseAddr(host); err != nil { // not ip
|
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()
|
mutex.RLock()
|
||||||
defer mutex.RUnlock()
|
defer mutex.RUnlock()
|
||||||
@ -74,6 +82,21 @@ func Listen(network, address string) (net.Listener, error) {
|
|||||||
return ListenContext(context.Background(), network, address)
|
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() {
|
func init() {
|
||||||
keepalive.SetDisableKeepAliveCallback.Register(func(b bool) {
|
keepalive.SetDisableKeepAliveCallback.Register(func(b bool) {
|
||||||
mutex.Lock()
|
mutex.Lock()
|
||||||
|
30
common/sockopt/reuse_common.go
Normal file
30
common/sockopt/reuse_common.go
Normal file
@ -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
|
||||||
|
}
|
@ -1,9 +1,5 @@
|
|||||||
//go:build !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !windows
|
//go:build !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !windows
|
||||||
|
|
||||||
package dialer
|
package sockopt
|
||||||
|
|
||||||
import (
|
func reuseControl(fd uintptr) error { return nil }
|
||||||
"net"
|
|
||||||
)
|
|
||||||
|
|
||||||
func addrReuseToListenConfig(*net.ListenConfig) {}
|
|
22
common/sockopt/reuse_unix.go
Normal file
22
common/sockopt/reuse_unix.go
Normal file
@ -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
common/sockopt/reuse_windows.go
Normal file
9
common/sockopt/reuse_windows.go
Normal file
@ -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)
|
||||||
|
}
|
@ -1,19 +0,0 @@
|
|||||||
package sockopt
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
func UDPReuseaddr(c *net.UDPConn) (err error) {
|
|
||||||
rc, err := c.SyscallConn()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
rc.Control(func(fd uintptr) {
|
|
||||||
err = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
|
|
||||||
})
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
//go:build !linux
|
|
||||||
|
|
||||||
package sockopt
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
)
|
|
||||||
|
|
||||||
func UDPReuseaddr(c *net.UDPConn) (err error) {
|
|
||||||
return
|
|
||||||
}
|
|
@ -5,13 +5,11 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
"github.com/metacubex/mihomo/common/sockopt"
|
||||||
)
|
)
|
||||||
|
|
||||||
func addrReuseToListenConfig(lc *net.ListenConfig) {
|
func addrReuseToListenConfig(lc *net.ListenConfig) {
|
||||||
addControlToListenConfig(lc, func(ctx context.Context, network, address string, c syscall.RawConn) error {
|
addControlToListenConfig(lc, func(ctx context.Context, network, address string, c syscall.RawConn) error {
|
||||||
return c.Control(func(fd uintptr) {
|
return sockopt.RawConnReuseaddr(c)
|
||||||
windows.SetsockoptInt(windows.Handle(fd), windows.SOL_SOCKET, windows.SO_REUSEADDR, 1)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
@ -1,20 +0,0 @@
|
|||||||
//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
|
||||||
|
|
||||||
package dialer
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net"
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
)
|
|
||||||
|
|
||||||
func addrReuseToListenConfig(lc *net.ListenConfig) {
|
|
||||||
addControlToListenConfig(lc, func(ctx context.Context, network, address string, c syscall.RawConn) error {
|
|
||||||
return c.Control(func(fd uintptr) {
|
|
||||||
unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEADDR, 1)
|
|
||||||
unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
@ -5,6 +5,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
"github.com/metacubex/mihomo/adapter/inbound"
|
||||||
"github.com/metacubex/mihomo/common/sockopt"
|
"github.com/metacubex/mihomo/common/sockopt"
|
||||||
"github.com/metacubex/mihomo/context"
|
"github.com/metacubex/mihomo/context"
|
||||||
"github.com/metacubex/mihomo/log"
|
"github.com/metacubex/mihomo/log"
|
||||||
@ -20,8 +21,9 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
*D.Server
|
|
||||||
handler handler
|
handler handler
|
||||||
|
tcpServer *D.Server
|
||||||
|
udpServer *D.Server
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServeDNS implement D.Handler ServeDNS
|
// ServeDNS implement D.Handler ServeDNS
|
||||||
@ -55,12 +57,19 @@ func ReCreateServer(addr string, resolver *Resolver, mapper *ResolverEnhancer) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if server.Server != nil {
|
if server.tcpServer != nil {
|
||||||
server.Shutdown()
|
_ = server.tcpServer.Shutdown()
|
||||||
server = &Server{}
|
server.tcpServer = nil
|
||||||
address = ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if server.udpServer != nil {
|
||||||
|
_ = server.udpServer.Shutdown()
|
||||||
|
server.udpServer = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
server.handler = nil
|
||||||
|
address = ""
|
||||||
|
|
||||||
if addr == "" {
|
if addr == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -77,31 +86,36 @@ func ReCreateServer(addr string, resolver *Resolver, mapper *ResolverEnhancer) {
|
|||||||
return
|
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
|
address = addr
|
||||||
handler := NewHandler(resolver, mapper)
|
handler := NewHandler(resolver, mapper)
|
||||||
server = &Server{handler: handler}
|
server = &Server{handler: handler}
|
||||||
server.Server = &D.Server{Addr: addr, PacketConn: p, Handler: server}
|
|
||||||
|
|
||||||
go func() {
|
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())
|
|
||||||
}
|
}
|
||||||
|
@ -18,13 +18,12 @@ type UDPListener struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewUDP(addr string, pickCipher core.Cipher, tunnel C.Tunnel, additions ...inbound.Addition) (*UDPListener, error) {
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = sockopt.UDPReuseaddr(l.(*net.UDPConn))
|
if err := sockopt.UDPReuseaddr(l); err != nil {
|
||||||
if err != nil {
|
|
||||||
log.Warnln("Failed to Reuse UDP Address: %s", err)
|
log.Warnln("Failed to Reuse UDP Address: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,13 +140,12 @@ func New(config LC.Hysteria2Server, tunnel C.Tunnel, additions ...inbound.Additi
|
|||||||
_service := *service
|
_service := *service
|
||||||
service := &_service // make a copy
|
service := &_service // make a copy
|
||||||
|
|
||||||
ul, err := net.ListenPacket("udp", addr)
|
ul, err := inbound.ListenPacket("udp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = sockopt.UDPReuseaddr(ul.(*net.UDPConn))
|
if err := sockopt.UDPReuseaddr(ul); err != nil {
|
||||||
if err != nil {
|
|
||||||
log.Warnln("Failed to Reuse UDP Address: %s", err)
|
log.Warnln("Failed to Reuse UDP Address: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,13 +82,12 @@ func New(config LC.ShadowsocksServer, tunnel C.Tunnel, additions ...inbound.Addi
|
|||||||
|
|
||||||
if config.Udp {
|
if config.Udp {
|
||||||
//UDP
|
//UDP
|
||||||
ul, err := net.ListenPacket("udp", addr)
|
ul, err := inbound.ListenPacket("udp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = sockopt.UDPReuseaddr(ul.(*net.UDPConn))
|
if err := sockopt.UDPReuseaddr(ul); err != nil {
|
||||||
if err != nil {
|
|
||||||
log.Warnln("Failed to Reuse UDP Address: %s", err)
|
log.Warnln("Failed to Reuse UDP Address: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,12 +40,12 @@ func NewUDP(addr string, tunnel C.Tunnel, additions ...inbound.Addition) (*UDPLi
|
|||||||
inbound.WithSpecialRules(""),
|
inbound.WithSpecialRules(""),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
l, err := net.ListenPacket("udp", addr)
|
l, err := inbound.ListenPacket("udp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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)
|
log.Warnln("Failed to Reuse UDP Address: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,13 +152,12 @@ func New(config LC.TuicServer, tunnel C.Tunnel, additions ...inbound.Addition) (
|
|||||||
for _, addr := range strings.Split(config.Listen, ",") {
|
for _, addr := range strings.Split(config.Listen, ",") {
|
||||||
addr := addr
|
addr := addr
|
||||||
|
|
||||||
ul, err := net.ListenPacket("udp", addr)
|
ul, err := inbound.ListenPacket("udp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = sockopt.UDPReuseaddr(ul.(*net.UDPConn))
|
if err := sockopt.UDPReuseaddr(ul); err != nil {
|
||||||
if err != nil {
|
|
||||||
log.Warnln("Failed to Reuse UDP Address: %s", err)
|
log.Warnln("Failed to Reuse UDP Address: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user