feat: io tcp reset support (forward only)

This commit is contained in:
Toby 2024-03-20 19:01:26 -07:00
parent 6ad7714c9a
commit 57c818038c
5 changed files with 48 additions and 8 deletions

View File

@ -78,6 +78,7 @@ io:
rcvBuf: 4194304
sndBuf: 4194304
local: true # FORWARD チェーンで OpenGFW を実行したい場合は false に設定する
rst: false # ブロックされたTCP接続に対してRSTを送信する場合はtrueに設定してください。local=falseのみです
workers:
count: 4

View File

@ -82,6 +82,7 @@ io:
rcvBuf: 4194304
sndBuf: 4194304
local: true # set to false if you want to run OpenGFW on FORWARD chain
rst: false # set to true if you want to send RST for blocked TCP connections, local=false only
workers:
count: 4

View File

@ -78,6 +78,7 @@ io:
rcvBuf: 4194304
sndBuf: 4194304
local: true # 如果需要在 FORWARD 链上运行 OpenGFW请设置为 false
rst: false # 是否对要阻断的 TCP 连接发送 RST。仅在 local=false 时有效
workers:
count: 4

View File

@ -171,6 +171,7 @@ type cliConfigIO struct {
ReadBuffer int `mapstructure:"rcvBuf"`
WriteBuffer int `mapstructure:"sndBuf"`
Local bool `mapstructure:"local"`
RST bool `mapstructure:"rst"`
}
type cliConfigWorkers struct {
@ -197,6 +198,7 @@ func (c *cliConfig) fillIO(config *engine.Config) error {
ReadBuffer: c.IO.ReadBuffer,
WriteBuffer: c.IO.WriteBuffer,
Local: c.IO.Local,
RST: c.IO.RST,
})
if err != nil {
return configError{Field: "io", Err: err}

View File

@ -43,6 +43,23 @@ table %s %s {
}
`, nfqueueConnMarkAccept, nfqueueConnMarkDrop, nfqueueNum, nftFamily, nftTable)
var nftRulesForwardRST = fmt.Sprintf(`
define ACCEPT_CTMARK=%d
define DROP_CTMARK=%d
define QUEUE_NUM=%d
table %s %s {
chain FORWARD {
type filter hook forward priority filter; policy accept;
ct mark $ACCEPT_CTMARK counter accept
ip protocol tcp ct mark $DROP_CTMARK counter reject with tcp reset
ct mark $DROP_CTMARK counter drop
counter queue num $QUEUE_NUM bypass
}
}
`, nfqueueConnMarkAccept, nfqueueConnMarkDrop, nfqueueNum, nftFamily, nftTable)
var nftRulesLocal = fmt.Sprintf(`
define ACCEPT_CTMARK=%d
define DROP_CTMARK=%d
@ -72,6 +89,13 @@ var iptRulesForward = []iptRule{
{"filter", "FORWARD", []string{"-j", "NFQUEUE", "--queue-num", strconv.Itoa(nfqueueNum), "--queue-bypass"}},
}
var iptRulesForwardRST = []iptRule{
{"filter", "FORWARD", []string{"-m", "connmark", "--mark", strconv.Itoa(nfqueueConnMarkAccept), "-j", "ACCEPT"}},
{"filter", "FORWARD", []string{"-p", "tcp", "-m", "connmark", "--mark", strconv.Itoa(nfqueueConnMarkDrop), "-j", "REJECT", "--reject-with", "tcp-reset"}},
{"filter", "FORWARD", []string{"-m", "connmark", "--mark", strconv.Itoa(nfqueueConnMarkDrop), "-j", "DROP"}},
{"filter", "FORWARD", []string{"-j", "NFQUEUE", "--queue-num", strconv.Itoa(nfqueueNum), "--queue-bypass"}},
}
var iptRulesLocal = []iptRule{
{"filter", "INPUT", []string{"-m", "connmark", "--mark", strconv.Itoa(nfqueueConnMarkAccept), "-j", "ACCEPT"}},
{"filter", "INPUT", []string{"-m", "connmark", "--mark", strconv.Itoa(nfqueueConnMarkDrop), "-j", "DROP"}},
@ -89,6 +113,7 @@ var errNotNFQueuePacket = errors.New("not an NFQueue packet")
type nfqueuePacketIO struct {
n *nfqueue.Nfqueue
local bool
rst bool
rSet bool // whether the nftables/iptables rules have been set
// iptables not nil = use iptables instead of nftables
@ -101,6 +126,7 @@ type NFQueuePacketIOConfig struct {
ReadBuffer int
WriteBuffer int
Local bool
RST bool
}
func NewNFQueuePacketIO(config NFQueuePacketIOConfig) (PacketIO, error) {
@ -147,6 +173,7 @@ func NewNFQueuePacketIO(config NFQueuePacketIOConfig) (PacketIO, error) {
return &nfqueuePacketIO{
n: n,
local: config.Local,
rst: config.RST,
ipt4: ipt4,
ipt6: ipt6,
}, nil
@ -182,9 +209,9 @@ func (n *nfqueuePacketIO) Register(ctx context.Context, cb PacketCallback) error
}
if !n.rSet {
if n.ipt4 != nil {
err = n.setupIpt(n.local, false)
err = n.setupIpt(n.local, n.rst, false)
} else {
err = n.setupNft(n.local, false)
err = n.setupNft(n.local, n.rst, false)
}
if err != nil {
return err
@ -238,22 +265,26 @@ func (n *nfqueuePacketIO) SetVerdict(p Packet, v Verdict, newPacket []byte) erro
func (n *nfqueuePacketIO) Close() error {
if n.rSet {
if n.ipt4 != nil {
_ = n.setupIpt(n.local, true)
_ = n.setupIpt(n.local, n.rst, true)
} else {
_ = n.setupNft(n.local, true)
_ = n.setupNft(n.local, n.rst, true)
}
n.rSet = false
}
return n.n.Close()
}
func (n *nfqueuePacketIO) setupNft(local, remove bool) error {
func (n *nfqueuePacketIO) setupNft(local, rst, remove bool) error {
var rules string
if local {
rules = nftRulesLocal
} else {
if rst {
rules = nftRulesForwardRST
} else {
rules = nftRulesForward
}
}
var err error
if remove {
err = nftDelete(nftFamily, nftTable)
@ -268,13 +299,17 @@ func (n *nfqueuePacketIO) setupNft(local, remove bool) error {
return nil
}
func (n *nfqueuePacketIO) setupIpt(local, remove bool) error {
func (n *nfqueuePacketIO) setupIpt(local, rst, remove bool) error {
var rules []iptRule
if local {
rules = iptRulesLocal
} else {
if rst {
rules = iptRulesForwardRST
} else {
rules = iptRulesForward
}
}
var err error
if remove {
err = iptsBatchDeleteIfExists([]*iptables.IPTables{n.ipt4, n.ipt6}, rules)