//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 }