Fix nfqueue fallback when kernel module unavailable

This commit is contained in:
世界 2025-12-31 02:18:51 +08:00
parent a850c4f8a1
commit a5db80d710
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
2 changed files with 14 additions and 20 deletions

View file

@ -5,7 +5,6 @@ package tun
import ( import (
"context" "context"
"errors" "errors"
"sync"
"sync/atomic" "sync/atomic"
"github.com/sagernet/sing-tun/internal/gtcpip/header" "github.com/sagernet/sing-tun/internal/gtcpip/header"
@ -30,7 +29,6 @@ type nfqueueHandler struct {
queue uint16 queue uint16
outputMark uint32 outputMark uint32
resetMark uint32 resetMark uint32
wg sync.WaitGroup
closed atomic.Bool closed atomic.Bool
} }
@ -82,28 +80,25 @@ func (h *nfqueueHandler) Start() error {
if err != nil { if err != nil {
return E.Cause(err, "open nfqueue") return E.Cause(err, "open nfqueue")
} }
h.nfq = nfq
if err = nfq.SetOption(netlink.NoENOBUFS, true); err != nil { if err = nfq.SetOption(netlink.NoENOBUFS, true); err != nil {
h.nfq.Close() nfq.Close()
return E.Cause(err, "set nfqueue option") return E.Cause(err, "set nfqueue option")
} }
h.wg.Add(1) err = nfq.RegisterWithErrorFunc(h.ctx, h.handlePacket, func(e error) int {
go func() { if h.ctx.Err() != nil {
defer h.wg.Done() return 1
err := nfq.RegisterWithErrorFunc(h.ctx, h.handlePacket, func(e error) int {
if h.ctx.Err() != nil {
return 1
}
h.logger.Error("nfqueue error: ", e)
return 0
})
if err != nil && h.ctx.Err() == nil {
h.logger.Error("nfqueue register error: ", err)
} }
}() h.logger.Error("nfqueue error: ", e)
return 0
})
if err != nil {
nfq.Close()
return E.Cause(err, "register nfqueue")
}
h.nfq = nfq
return nil return nil
} }
@ -239,6 +234,5 @@ func (h *nfqueueHandler) Close() error {
if h.nfq != nil { if h.nfq != nil {
h.nfq.Close() h.nfq.Close()
} }
h.wg.Wait()
return nil return nil
} }

View file

@ -143,9 +143,9 @@ func (r *autoRedirect) Start() error {
ResetMark: r.effectiveResetMark(), ResetMark: r.effectiveResetMark(),
}) })
if err != nil { if err != nil {
r.logger.Warn("nfqueue not available, pre-match disabled: ", err) r.logger.Warn("nfqueue not available, pre-match disabled (missing nfnetlink_queue and nft_queue kernel module?): ", err)
} else if err = handler.Start(); err != nil { } else if err = handler.Start(); err != nil {
r.logger.Warn("nfqueue start failed, pre-match disabled: ", err) r.logger.Warn("nfqueue start failed, pre-match disabled (missing nfnetlink_queue and nft_queue kernel module?): ", err)
} else { } else {
r.nfqueueHandler = handler r.nfqueueHandler = handler
r.nfqueueEnabled = true r.nfqueueEnabled = true