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

View File

@ -82,6 +82,7 @@ io:
rcvBuf: 4194304 rcvBuf: 4194304
sndBuf: 4194304 sndBuf: 4194304
local: true # set to false if you want to run OpenGFW on FORWARD chain 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: workers:
count: 4 count: 4

View File

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

View File

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

View File

@ -43,6 +43,23 @@ table %s %s {
} }
`, nfqueueConnMarkAccept, nfqueueConnMarkDrop, nfqueueNum, nftFamily, nftTable) `, 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(` var nftRulesLocal = fmt.Sprintf(`
define ACCEPT_CTMARK=%d define ACCEPT_CTMARK=%d
define DROP_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"}}, {"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{ var iptRulesLocal = []iptRule{
{"filter", "INPUT", []string{"-m", "connmark", "--mark", strconv.Itoa(nfqueueConnMarkAccept), "-j", "ACCEPT"}}, {"filter", "INPUT", []string{"-m", "connmark", "--mark", strconv.Itoa(nfqueueConnMarkAccept), "-j", "ACCEPT"}},
{"filter", "INPUT", []string{"-m", "connmark", "--mark", strconv.Itoa(nfqueueConnMarkDrop), "-j", "DROP"}}, {"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 { type nfqueuePacketIO struct {
n *nfqueue.Nfqueue n *nfqueue.Nfqueue
local bool local bool
rst bool
rSet bool // whether the nftables/iptables rules have been set rSet bool // whether the nftables/iptables rules have been set
// iptables not nil = use iptables instead of nftables // iptables not nil = use iptables instead of nftables
@ -101,6 +126,7 @@ type NFQueuePacketIOConfig struct {
ReadBuffer int ReadBuffer int
WriteBuffer int WriteBuffer int
Local bool Local bool
RST bool
} }
func NewNFQueuePacketIO(config NFQueuePacketIOConfig) (PacketIO, error) { func NewNFQueuePacketIO(config NFQueuePacketIOConfig) (PacketIO, error) {
@ -147,6 +173,7 @@ func NewNFQueuePacketIO(config NFQueuePacketIOConfig) (PacketIO, error) {
return &nfqueuePacketIO{ return &nfqueuePacketIO{
n: n, n: n,
local: config.Local, local: config.Local,
rst: config.RST,
ipt4: ipt4, ipt4: ipt4,
ipt6: ipt6, ipt6: ipt6,
}, nil }, nil
@ -182,9 +209,9 @@ func (n *nfqueuePacketIO) Register(ctx context.Context, cb PacketCallback) error
} }
if !n.rSet { if !n.rSet {
if n.ipt4 != nil { if n.ipt4 != nil {
err = n.setupIpt(n.local, false) err = n.setupIpt(n.local, n.rst, false)
} else { } else {
err = n.setupNft(n.local, false) err = n.setupNft(n.local, n.rst, false)
} }
if err != nil { if err != nil {
return err return err
@ -238,22 +265,26 @@ func (n *nfqueuePacketIO) SetVerdict(p Packet, v Verdict, newPacket []byte) erro
func (n *nfqueuePacketIO) Close() error { func (n *nfqueuePacketIO) Close() error {
if n.rSet { if n.rSet {
if n.ipt4 != nil { if n.ipt4 != nil {
_ = n.setupIpt(n.local, true) _ = n.setupIpt(n.local, n.rst, true)
} else { } else {
_ = n.setupNft(n.local, true) _ = n.setupNft(n.local, n.rst, true)
} }
n.rSet = false n.rSet = false
} }
return n.n.Close() return n.n.Close()
} }
func (n *nfqueuePacketIO) setupNft(local, remove bool) error { func (n *nfqueuePacketIO) setupNft(local, rst, remove bool) error {
var rules string var rules string
if local { if local {
rules = nftRulesLocal rules = nftRulesLocal
} else {
if rst {
rules = nftRulesForwardRST
} else { } else {
rules = nftRulesForward rules = nftRulesForward
} }
}
var err error var err error
if remove { if remove {
err = nftDelete(nftFamily, nftTable) err = nftDelete(nftFamily, nftTable)
@ -268,13 +299,17 @@ func (n *nfqueuePacketIO) setupNft(local, remove bool) error {
return nil return nil
} }
func (n *nfqueuePacketIO) setupIpt(local, remove bool) error { func (n *nfqueuePacketIO) setupIpt(local, rst, remove bool) error {
var rules []iptRule var rules []iptRule
if local { if local {
rules = iptRulesLocal rules = iptRulesLocal
} else {
if rst {
rules = iptRulesForwardRST
} else { } else {
rules = iptRulesForward rules = iptRulesForward
} }
}
var err error var err error
if remove { if remove {
err = iptsBatchDeleteIfExists([]*iptables.IPTables{n.ipt4, n.ipt6}, rules) err = iptsBatchDeleteIfExists([]*iptables.IPTables{n.ipt4, n.ipt6}, rules)