Fix: set SO_REUSEADDR for UDP listeners on linux (#630)

This commit is contained in:
duama 2020-04-11 21:45:56 +08:00 committed by GitHub
parent 3ccd7def86
commit 2750c7ead0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 48 additions and 1 deletions

View File

@ -0,0 +1,19 @@
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
}

View File

@ -0,0 +1,11 @@
// +build !linux
package sockopt
import (
"net"
)
func UDPReuseaddr(c *net.UDPConn) (err error) {
return
}

View File

@ -3,6 +3,8 @@ package dns
import (
"net"
"github.com/Dreamacro/clash/common/sockopt"
D "github.com/miekg/dns"
)
@ -58,6 +60,11 @@ func ReCreateServer(addr string, resolver *Resolver) error {
return err
}
err = sockopt.UDPReuseaddr(p)
if err != nil {
return err
}
address = addr
handler := newHandler(resolver)
server = &Server{handler: handler}

View File

@ -31,7 +31,11 @@ func setsockopt(c *net.UDPConn, addr string) error {
}
rc.Control(func(fd uintptr) {
err = syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_TRANSPARENT, 1)
err = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
if err == nil {
err = syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_TRANSPARENT, 1)
}
if err == nil && isIPv6 {
err = syscall.SetsockoptInt(int(fd), syscall.SOL_IPV6, IPV6_TRANSPARENT, 1)
}

View File

@ -5,6 +5,7 @@ import (
adapters "github.com/Dreamacro/clash/adapters/inbound"
"github.com/Dreamacro/clash/common/pool"
"github.com/Dreamacro/clash/common/sockopt"
"github.com/Dreamacro/clash/component/socks5"
C "github.com/Dreamacro/clash/constant"
"github.com/Dreamacro/clash/tunnel"
@ -22,6 +23,11 @@ func NewSocksUDPProxy(addr string) (*SockUDPListener, error) {
return nil, err
}
err = sockopt.UDPReuseaddr(l.(*net.UDPConn))
if err != nil {
return nil, err
}
sl := &SockUDPListener{l, addr, false}
go func() {
for {