From 57c818038cb0dfa11a807939b4fdf6e3d4c275ba Mon Sep 17 00:00:00 2001 From: Toby Date: Wed, 20 Mar 2024 19:01:26 -0700 Subject: [PATCH] feat: io tcp reset support (forward only) --- README.ja.md | 1 + README.md | 1 + README.zh.md | 1 + cmd/root.go | 2 ++ io/nfqueue.go | 51 +++++++++++++++++++++++++++++++++++++++++++-------- 5 files changed, 48 insertions(+), 8 deletions(-) diff --git a/README.ja.md b/README.ja.md index b3acc30..5757cc5 100644 --- a/README.ja.md +++ b/README.ja.md @@ -78,6 +78,7 @@ io: rcvBuf: 4194304 sndBuf: 4194304 local: true # FORWARD チェーンで OpenGFW を実行したい場合は false に設定する + rst: false # ブロックされたTCP接続に対してRSTを送信する場合はtrueに設定してください。local=falseのみです workers: count: 4 diff --git a/README.md b/README.md index 50758a2..7da03e1 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/README.zh.md b/README.zh.md index 5580c16..66d00bc 100644 --- a/README.zh.md +++ b/README.zh.md @@ -78,6 +78,7 @@ io: rcvBuf: 4194304 sndBuf: 4194304 local: true # 如果需要在 FORWARD 链上运行 OpenGFW,请设置为 false + rst: false # 是否对要阻断的 TCP 连接发送 RST。仅在 local=false 时有效 workers: count: 4 diff --git a/cmd/root.go b/cmd/root.go index 0c8fa77..7e54462 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -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} diff --git a/io/nfqueue.go b/io/nfqueue.go index 2c1cff2..8667b8f 100644 --- a/io/nfqueue.go +++ b/io/nfqueue.go @@ -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,21 +265,25 @@ 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 { - rules = nftRulesForward + if rst { + rules = nftRulesForwardRST + } else { + rules = nftRulesForward + } } var err error if remove { @@ -268,12 +299,16 @@ 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 { - rules = iptRulesForward + if rst { + rules = iptRulesForwardRST + } else { + rules = iptRulesForward + } } var err error if remove {