Files
sing-tun/redirect_nftables_rules_openwrt.go
2025-08-03 00:12:24 +08:00

53 lines
1.5 KiB
Go

//go:build linux
package tun
import (
"os"
"os/exec"
"github.com/sagernet/nftables"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/shell"
)
func (r *autoRedirect) configureOpenWRTFirewall4(nft *nftables.Conn, cleanup bool) error {
_, err := nft.ListTableOfFamily("fw4", nftables.TableFamilyINet)
if err != nil {
return nil
}
fw4Path, err := exec.LookPath("fw4")
if err != nil {
return nil
}
rulePath := "/etc/nftables.d/0-" + r.tableName + "-auto-redirect.nft"
if !cleanup {
err = os.WriteFile(rulePath, []byte(`chain input {
type filter hook input priority filter; policy accept;
iifname "`+r.tunOptions.Name+`" counter accept comment "!`+r.tableName+`: Accept traffic from tun"
oifname "`+r.tunOptions.Name+`" counter accept comment "!`+r.tableName+`: Accept traffic from tun"
}
chain forward {
type filter hook forward priority filter; policy accept;
iifname "`+r.tunOptions.Name+`" counter accept comment "!`+r.tableName+`: Accept traffic from tun"
oifname "`+r.tunOptions.Name+`" counter accept comment "!`+r.tableName+`: Accept traffic from tun"
}
`), 0o644)
if err != nil {
return E.Cause(err, "write fw4 rules")
}
} else if _, err = os.Stat(rulePath); os.IsNotExist(err) {
return nil
} else {
err = os.Remove(rulePath)
if err != nil {
return E.Cause(err, "clean fw4 rules")
}
}
output, err := shell.Exec(fw4Path, "reload").Read()
if err != nil {
return E.Extend(E.Cause(err, "reload fw4 rules"), output)
}
return nil
}