From 3f98c35e6240a566591324f047741623b0c687ad Mon Sep 17 00:00:00 2001 From: SunBK201 Date: Sat, 29 Nov 2025 15:50:50 +0800 Subject: [PATCH] feat: add ipv6 support --- src/internal/netfilter/firewall.go | 39 +++++++++++++++++++ src/internal/server/nfqueue/nfqueue_linux.go | 2 +- src/internal/server/nfqueue/nftables.go | 6 +++ src/internal/server/redirect/nftables.go | 6 +++ .../server/redirect/redirect_linux.go | 2 +- src/internal/server/tproxy/nftables.go | 17 ++++++-- src/internal/server/tproxy/tproxy_linux.go | 2 +- 7 files changed, 68 insertions(+), 6 deletions(-) diff --git a/src/internal/netfilter/firewall.go b/src/internal/netfilter/firewall.go index 76f090d..88cf3f6 100644 --- a/src/internal/netfilter/firewall.go +++ b/src/internal/netfilter/firewall.go @@ -50,6 +50,17 @@ var LAN_CIDRS = []string{ "240.0.0.0/4", } +var LAN6_CIDRS = []string{ + "::/128", + "::1/128", + "::ffff:0:0/96", + "64:ff9b::/96", + "2001:db8::/32", + "fc00::/7", + "fe80::/10", + "ff00::/8", +} + var ( IptRuleIgnoreBrLAN = []string{ "!", "-i", "br-lan", @@ -89,6 +100,10 @@ var ( fmt.Sprintf("ip daddr @%s", LANSET), "return", ) + NftRuleIgnoreLAN6 = knftables.Concat( + fmt.Sprintf("ip6 daddr @%s", LANSET+"_6"), + "return", + ) NftRuleIgnorePorts = knftables.Concat( fmt.Sprintf("tcp dport { %s }", SKIP_PORTS), "return", @@ -194,6 +209,30 @@ func (f *Firewall) NftSetLanIP(tx *knftables.Transaction, table *knftables.Table } } +func (f *Firewall) NftSetLanIP6(tx *knftables.Transaction, table *knftables.Table) { + ipset := &knftables.Set{ + Name: LANSET + "_6", + Table: table.Name, + Family: table.Family, + Type: "ipv6_addr", + Flags: []knftables.SetFlag{ + knftables.IntervalFlag, + }, + AutoMerge: knftables.PtrTo(true), + } + tx.Add(ipset) + + for _, cidr := range LAN6_CIDRS { + ip6lan := &knftables.Element{ + Table: table.Name, + Family: table.Family, + Set: ipset.Name, + Key: []string{cidr}, + } + tx.Add(ip6lan) + } +} + func (f *Firewall) IptSetLanIP() error { if err := ipset.Check(); err != nil { return err diff --git a/src/internal/server/nfqueue/nfqueue_linux.go b/src/internal/server/nfqueue/nfqueue_linux.go index 3a17763..ea56186 100644 --- a/src/internal/server/nfqueue/nfqueue_linux.go +++ b/src/internal/server/nfqueue/nfqueue_linux.go @@ -47,7 +47,7 @@ func New(cfg *config.Config, rw *rewrite.Rewriter) *Server { s.Firewall = netfilter.Firewall{ Nftable: &knftables.Table{ Name: "UA3F", - Family: knftables.IPv4Family, + Family: knftables.InetFamily, }, NftSetup: s.nftSetup, NftCleanup: s.nftCleanup, diff --git a/src/internal/server/nfqueue/nftables.go b/src/internal/server/nfqueue/nftables.go index 48f524f..6a9f259 100644 --- a/src/internal/server/nfqueue/nftables.go +++ b/src/internal/server/nfqueue/nftables.go @@ -20,6 +20,7 @@ func (s *Server) nftSetup() error { tx.Add(s.Nftable) s.NftSetLanIP(tx, s.Nftable) + s.NftSetLanIP6(tx, s.Nftable) s.NftSetNfqueue(tx, s.Nftable) if err := nft.Run(context.TODO(), tx); err != nil { @@ -68,6 +69,11 @@ func (s *Server) NftSetNfqueue(tx *knftables.Transaction, table *knftables.Table Rule: netfilter.NftRuleIgnoreLAN, }) + tx.Add(&knftables.Rule{ + Chain: chain.Name, + Rule: netfilter.NftRuleIgnoreLAN6, + }) + tx.Add(&knftables.Rule{ Chain: chain.Name, Rule: netfilter.NftRuleIgnorePorts, diff --git a/src/internal/server/redirect/nftables.go b/src/internal/server/redirect/nftables.go index 33b0e14..c8c402d 100644 --- a/src/internal/server/redirect/nftables.go +++ b/src/internal/server/redirect/nftables.go @@ -20,6 +20,7 @@ func (s *Server) nftSetup() error { tx.Add(s.Nftable) s.NftSetLanIP(tx, s.Nftable) + s.NftSetLanIP6(tx, s.Nftable) s.NftSetRedirect(tx, s.Nftable) if err := nft.Run(context.TODO(), tx); err != nil { @@ -73,6 +74,11 @@ func (s *Server) NftSetRedirect(tx *knftables.Transaction, table *knftables.Tabl Rule: netfilter.NftRuleIgnoreLAN, }) + tx.Add(&knftables.Rule{ + Chain: chain.Name, + Rule: netfilter.NftRuleIgnoreLAN6, + }) + tx.Add(&knftables.Rule{ Chain: chain.Name, Rule: netfilter.NftRuleIgnorePorts, diff --git a/src/internal/server/redirect/redirect_linux.go b/src/internal/server/redirect/redirect_linux.go index ca0ecaa..4572a5f 100644 --- a/src/internal/server/redirect/redirect_linux.go +++ b/src/internal/server/redirect/redirect_linux.go @@ -37,7 +37,7 @@ func New(cfg *config.Config, rw *rewrite.Rewriter) *Server { s.Firewall = netfilter.Firewall{ Nftable: &knftables.Table{ Name: "UA3F", - Family: knftables.IPv4Family, + Family: knftables.InetFamily, }, NftSetup: s.nftSetup, NftCleanup: s.nftCleanup, diff --git a/src/internal/server/tproxy/nftables.go b/src/internal/server/tproxy/nftables.go index 65d5f6b..42e20c2 100644 --- a/src/internal/server/tproxy/nftables.go +++ b/src/internal/server/tproxy/nftables.go @@ -26,6 +26,7 @@ func (s *Server) nftSetup() error { tx.Add(s.Nftable) s.NftSetLanIP(tx, s.Nftable) + s.NftSetLanIP6(tx, s.Nftable) s.NftSetTproxy(tx, s.Nftable) if err := nft.Run(context.TODO(), tx); err != nil { @@ -66,7 +67,7 @@ func (s *Server) NftSetTproxy(tx *knftables.Transaction, table *knftables.Table) "meta l4proto tcp", "mark", s.tproxyFwMark, "mark set 7894", - fmt.Sprintf("tproxy to 127.0.0.1:%d", s.Cfg.Port), + fmt.Sprintf("tproxy ip to 127.0.0.1:%d", s.Cfg.Port), "counter accept", ), }) @@ -101,6 +102,11 @@ func (s *Server) NftSetTproxy(tx *knftables.Transaction, table *knftables.Table) Rule: netfilter.NftRuleIgnoreLAN, }) + tx.Add(&knftables.Rule{ + Chain: prerouting.Name, + Rule: netfilter.NftRuleIgnoreLAN6, + }) + tx.Add(&knftables.Rule{ Chain: prerouting.Name, Rule: netfilter.NftRuleIgnorePorts, @@ -130,7 +136,7 @@ func (s *Server) NftSetTproxy(tx *knftables.Transaction, table *knftables.Table) Rule: knftables.Concat( "meta l4proto tcp", "mark", s.tproxyFwMark, - fmt.Sprintf("tproxy to 127.0.0.1:%d", s.Cfg.Port), + fmt.Sprintf("tproxy ip to 127.0.0.1:%d", s.Cfg.Port), "counter accept", ), }) @@ -141,7 +147,7 @@ func (s *Server) NftSetTproxy(tx *knftables.Transaction, table *knftables.Table) Rule: knftables.Concat( "meta l4proto tcp", "mark set", s.tproxyFwMark, - fmt.Sprintf("tproxy to 127.0.0.1:%d", s.Cfg.Port), + fmt.Sprintf("tproxy ip to 127.0.0.1:%d", s.Cfg.Port), "counter accept", ), }) @@ -175,6 +181,11 @@ func (s *Server) NftSetTproxy(tx *knftables.Transaction, table *knftables.Table) Rule: netfilter.NftRuleIgnoreLAN, }) + tx.Add(&knftables.Rule{ + Chain: output.Name, + Rule: netfilter.NftRuleIgnoreLAN6, + }) + tx.Add(&knftables.Rule{ Chain: output.Name, Rule: netfilter.NftRuleIgnorePorts, diff --git a/src/internal/server/tproxy/tproxy_linux.go b/src/internal/server/tproxy/tproxy_linux.go index 0d8c417..edfe77d 100644 --- a/src/internal/server/tproxy/tproxy_linux.go +++ b/src/internal/server/tproxy/tproxy_linux.go @@ -49,7 +49,7 @@ func New(cfg *config.Config, rw *rewrite.Rewriter) *Server { s.Firewall = netfilter.Firewall{ Nftable: &knftables.Table{ Name: "UA3F", - Family: knftables.IPv4Family, + Family: knftables.InetFamily, }, NftSetup: s.nftSetup, NftCleanup: s.nftCleanup,