mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-09-15 21:00:27 +00:00
Resolve and race all WireGuard addresses on handshake
This commit is contained in:
@@ -27,6 +27,7 @@ type ClientBind struct {
|
||||
bindCtx context.Context
|
||||
bindDone context.CancelFunc
|
||||
dialer N.Dialer
|
||||
reservedAccess sync.RWMutex
|
||||
reservedForEndpoint map[netip.AddrPort][3]uint8
|
||||
connAccess sync.Mutex
|
||||
conn *wireConn
|
||||
@@ -175,7 +176,9 @@ func (c *ClientBind) Send(bufs [][]byte, ep conn.Endpoint, offset int) error {
|
||||
buf = buf[offset:]
|
||||
}
|
||||
if len(buf) > 3 {
|
||||
c.reservedAccess.RLock()
|
||||
reserved, loaded := c.reservedForEndpoint[destination]
|
||||
c.reservedAccess.RUnlock()
|
||||
if !loaded {
|
||||
reserved = c.reserved
|
||||
}
|
||||
@@ -203,7 +206,9 @@ func (c *ClientBind) BatchSize() int {
|
||||
}
|
||||
|
||||
func (c *ClientBind) SetReservedForEndpoint(destination netip.AddrPort, reserved [3]byte) {
|
||||
c.reservedAccess.Lock()
|
||||
c.reservedForEndpoint[destination] = reserved
|
||||
c.reservedAccess.Unlock()
|
||||
}
|
||||
|
||||
type wireConn struct {
|
||||
|
||||
@@ -8,9 +8,7 @@ import (
|
||||
"net"
|
||||
"net/netip"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/sagernet/sing-box/common/dialer"
|
||||
"github.com/sagernet/sing-tun"
|
||||
@@ -133,24 +131,11 @@ func NewEndpoint(options EndpointOptions) (*Endpoint, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (e *Endpoint) Start(resolve bool) error {
|
||||
if common.Any(e.peers, func(peer peerConfig) bool {
|
||||
return !peer.endpoint.IsValid() && peer.destination.IsDomain()
|
||||
}) {
|
||||
if !resolve {
|
||||
return nil
|
||||
}
|
||||
for peerIndex, peer := range e.peers {
|
||||
if peer.endpoint.IsValid() || !peer.destination.IsDomain() {
|
||||
continue
|
||||
}
|
||||
destinationAddress, err := e.options.ResolvePeer(peer.destination.Fqdn)
|
||||
if err != nil {
|
||||
return E.Cause(err, "resolve endpoint domain for peer[", peerIndex, "]: ", peer.destination)
|
||||
}
|
||||
e.peers[peerIndex].endpoint = netip.AddrPortFrom(destinationAddress, peer.destination.Port)
|
||||
}
|
||||
} else if resolve {
|
||||
func (e *Endpoint) Start(postStart bool) error {
|
||||
hasDomainPeer := common.Any(e.peers, func(peer peerConfig) bool {
|
||||
return peer.destination.IsDomain()
|
||||
})
|
||||
if postStart != hasDomainPeer {
|
||||
return nil
|
||||
}
|
||||
var bind conn.Bind
|
||||
@@ -174,16 +159,18 @@ func (e *Endpoint) Start(resolve bool) error {
|
||||
connectAddr netip.AddrPort
|
||||
reserved [3]uint8
|
||||
)
|
||||
if len(e.peers) == 1 && e.peers[0].endpoint.IsValid() {
|
||||
isConnect = true
|
||||
connectAddr = e.peers[0].endpoint
|
||||
if len(e.peers) == 1 {
|
||||
reserved = e.peers[0].reserved
|
||||
if e.peers[0].endpoint.IsValid() {
|
||||
isConnect = true
|
||||
connectAddr = e.peers[0].endpoint
|
||||
}
|
||||
}
|
||||
bind = NewClientBind(e.options.Context, e.options.Logger, e.options.Dialer, isConnect, connectAddr, reserved)
|
||||
}
|
||||
if isUDPListener || len(e.peers) > 1 {
|
||||
for _, peer := range e.peers {
|
||||
if peer.reserved != [3]uint8{} {
|
||||
if peer.endpoint.IsValid() && peer.reserved != [3]uint8{} {
|
||||
bind.SetReservedForEndpoint(peer.endpoint, peer.reserved)
|
||||
}
|
||||
}
|
||||
@@ -212,12 +199,43 @@ func (e *Endpoint) Start(resolve bool) error {
|
||||
wgDevice.Close()
|
||||
return E.Cause(err, "setup wireguard: \n", ipcConf.String())
|
||||
}
|
||||
for _, peer := range e.peers {
|
||||
if !peer.destination.IsDomain() {
|
||||
continue
|
||||
}
|
||||
var publicKey device.NoisePublicKey
|
||||
common.Must(publicKey.FromHex(peer.publicKeyHex))
|
||||
wgPeer, found := wgDevice.LookupActivePeer(publicKey)
|
||||
if !found {
|
||||
wgDevice.Close()
|
||||
return E.New("missing configured peer: ", peer.destination)
|
||||
}
|
||||
wgPeer.SetEndpointResolver(func() ([]conn.Endpoint, error) {
|
||||
addresses, lookupErr := e.options.ResolvePeer(peer.destination.Fqdn)
|
||||
if lookupErr != nil {
|
||||
return nil, lookupErr
|
||||
}
|
||||
endpoints := make([]conn.Endpoint, 0, len(addresses))
|
||||
for _, address := range addresses {
|
||||
destination := netip.AddrPortFrom(address, peer.destination.Port)
|
||||
if peer.reserved != ([3]uint8{}) {
|
||||
bind.SetReservedForEndpoint(destination, peer.reserved)
|
||||
}
|
||||
endpoint, parseErr := bind.ParseEndpoint(destination.String())
|
||||
if parseErr != nil {
|
||||
return nil, parseErr
|
||||
}
|
||||
endpoints = append(endpoints, endpoint)
|
||||
}
|
||||
return endpoints, nil
|
||||
})
|
||||
}
|
||||
e.device = wgDevice
|
||||
e.pause = service.FromContext[pause.Manager](e.options.Context)
|
||||
if e.pause != nil {
|
||||
e.pauseCallback = e.pause.RegisterCallback(e.onPauseUpdated)
|
||||
}
|
||||
e.allowedIPs = (*device.AllowedIPs)(unsafe.Pointer(reflect.Indirect(reflect.ValueOf(wgDevice)).FieldByName("allowedips").UnsafeAddr()))
|
||||
e.allowedIPs = wgDevice.AllowedIPs()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ type EndpointOptions struct {
|
||||
Address []netip.Prefix
|
||||
PrivateKey string
|
||||
ListenPort uint16
|
||||
ResolvePeer func(domain string) (netip.Addr, error)
|
||||
ResolvePeer func(domain string) ([]netip.Addr, error)
|
||||
Peers []PeerOptions
|
||||
Workers int
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user