WireGuard proxy: Fix potential startup races (#6852)

https://github.com/XTLS/Xray-core/pull/6852#issuecomment-5871816550

Fixes https://github.com/XTLS/Xray-core/issues/6850
This commit is contained in:
v2ray authored and RPRX committed 2026-09-29 18:13:43 +00:00
1 parent 48ad0300ea
commit 08cb6e6bca
3 files changed
+25 -10

No files matched your search

+12 -2
View File
@@ -52,9 +52,12 @@ func (b *bind) Open(port uint16) (fns []conn.ReceiveFunc, actualPort uint16, err
case <-ch: case <-ch:
default: default:
errors.LogErrorInner(context.Background(), err, "unexpected closed") errors.LogErrorInner(context.Background(), err, "unexpected closed")
if b.downFunc != nil { b.mu.Lock()
downFunc := b.downFunc
b.mu.Unlock()
if downFunc != nil {
go func() { go func() {
common.Must(b.downFunc()) common.Must(downFunc())
}() }()
} }
} }
@@ -76,6 +79,13 @@ func (b *bind) Open(port uint16) (fns []conn.ReceiveFunc, actualPort uint16, err
}, uint16(c.LocalAddr().(*net.UDPAddr).Port), nil }, uint16(c.LocalAddr().(*net.UDPAddr).Port), nil
} }
// setDownFunc sets downFunc after the device is created, since the device may already be using the bind.
func (b *bind) setDownFunc(f func() error) {
b.mu.Lock()
defer b.mu.Unlock()
b.downFunc = f
}
func (b *bind) Close() error { func (b *bind) Close() error {
b.mu.Lock() b.mu.Lock()
defer b.mu.Unlock() defer b.mu.Unlock()
+8 -5
View File
@@ -288,7 +288,13 @@ func (h *Handler) init(ctx context.Context) error {
} }
return pktConn, nil return pktConn, nil
} }
bind := &bind{} // device.NewDevice may use the bind right away (Up -> BindUpdate -> Open),
// so everything it reads must be set before creating the device.
bind := &bind{
resolveFunc: resolveFunc,
listenFunc: listenFunc,
reserved: h.conf.Reserved,
}
logger := &device.Logger{ logger := &device.Logger{
Verbosef: func(format string, args ...any) { Verbosef: func(format string, args ...any) {
log.Record(&log.GeneralMessage{ log.Record(&log.GeneralMessage{
@@ -304,10 +310,7 @@ func (h *Handler) init(ctx context.Context) error {
}, },
} }
dev := device.NewDevice(h.tun, bind, logger) dev := device.NewDevice(h.tun, bind, logger)
bind.resolveFunc = resolveFunc bind.setDownFunc(dev.Down)
bind.listenFunc = listenFunc
bind.downFunc = dev.Down
bind.reserved = h.conf.Reserved
var cfg strings.Builder var cfg strings.Builder
cfg.WriteString("private_key=" + h.conf.SecretKey + "\n") cfg.WriteString("private_key=" + h.conf.SecretKey + "\n")
for _, peer := range h.conf.Peers { for _, peer := range h.conf.Peers {
+5 -3
View File
@@ -113,7 +113,7 @@ func NewServer(ctx context.Context, conf *DeviceConfig) (*Server, error) {
users.Store(user.Account.(*MemoryAccount).Pub, user) users.Store(user.Account.(*MemoryAccount).Pub, user)
} }
return &Server{ s := &Server{
conf: conf, conf: conf,
ctx: core.ToBackgroundDetachedContext(ctx), ctx: core.ToBackgroundDetachedContext(ctx),
policyManager: p, policyManager: p,
@@ -131,7 +131,10 @@ func NewServer(ctx context.Context, conf *DeviceConfig) (*Server, error) {
pub: pub, pub: pub,
users: users, users: users,
}, nil }
// Install the stack's protocol handlers before the device can deliver packets to it (Start -> dev.Up).
CreateForwarder(stack, s.HandleConnection)
return s, nil
} }
func (s *Server) AddUser(ctx context.Context, user *protocol.MemoryUser) error { func (s *Server) AddUser(ctx context.Context, user *protocol.MemoryUser) error {
@@ -320,7 +323,6 @@ func (s *Server) Start() error {
return err return err
} }
s.dev = dev s.dev = dev
CreateForwarder(s.stack, s.HandleConnection)
return nil return nil
} }