diff --git a/openwrt/files/luci/model/cbi/ua3f/fields.lua b/openwrt/files/luci/model/cbi/ua3f/fields.lua index 1c19155..1fff022 100644 --- a/openwrt/files/luci/model/cbi/ua3f/fields.lua +++ b/openwrt/files/luci/model/cbi/ua3f/fields.lua @@ -213,6 +213,10 @@ function M.add_others_fields(section) local tcpts = section:taboption("others", Flag, "del_tcpts", translate("Delete TCP Timestamps")) tcpts.description = translate("Remove TCP Timestamp option") + -- TCP Initial Window + local tcp_init_window = section:taboption("others", Flag, "set_tcp_init_window", translate("Set TCP Initial Window")) + tcp_init_window.description = translate("Set the TCP Initial Window to 65535 for SYN packets") + -- IP ID Setting local ipid = section:taboption("others", Flag, "set_ipid", translate("Set IP ID")) ipid.description = translate("Set the IP ID to 0 for packets") diff --git a/openwrt/files/ua3f.init b/openwrt/files/ua3f.init index d41d7cc..fea4f17 100755 --- a/openwrt/files/ua3f.init +++ b/openwrt/files/ua3f.init @@ -18,7 +18,7 @@ start_service() { local server_mode port bind ua log_level ua_regex partial_replace local rewrite_mode rewrite_rules - local set_ttl set_ipid del_tcpts + local set_ttl set_ipid del_tcpts set_tcp_init_window config_get server_mode "main" "server_mode" "TPROXY" config_get port "main" "port" "1080" config_get bind "main" "bind" "127.0.0.1" @@ -31,6 +31,7 @@ start_service() { config_get_bool set_ttl "main" "set_ttl" 0 config_get_bool set_ipid "main" "set_ipid" 0 config_get_bool del_tcpts "main" "del_tcpts" 0 + config_get_bool set_tcp_init_window "main" "set_tcp_init_window" 0 procd_open_instance "$NAME" procd_set_param command "$PROG" @@ -46,6 +47,7 @@ start_service() { procd_append_param env UA3F_TTL="$set_ttl" procd_append_param env UA3F_IPID="$set_ipid" procd_append_param env UA3F_TCPTS="$del_tcpts" + procd_append_param env UA3F_TCP_INIT_WINDOW="$set_tcp_init_window" procd_set_param respawn procd_set_param stdout 1 diff --git a/openwrt/files/ua3f.uci b/openwrt/files/ua3f.uci index 30d629a..8d2f355 100644 --- a/openwrt/files/ua3f.uci +++ b/openwrt/files/ua3f.uci @@ -14,4 +14,5 @@ config 'ua3f' 'main' option set_ttl '0' option del_tcpts '0' option set_ipid '0' + option set_tcp_init_window '0' option rewrite_rules '[{"enabled":false,"type":"DEST-PORT","action":"DIRECT","match_value":"443","rewrite_header":"User-Agent","rewrite_value":"","description":""},{"enabled":true,"type":"KEYWORD","action":"DIRECT","match_value":"MicroMessenger Client","rewrite_header":"User-Agent","rewrite_value":"","description":""},{"enabled":true,"type":"KEYWORD","action":"DIRECT","match_value":"Bilibili Freedoooooom\/MarkII","rewrite_header":"User-Agent","rewrite_value":"","description":""},{"enabled":true,"type":"KEYWORD","action":"DIRECT","match_value":"Valve\/Steam HTTP Client 1.0","rewrite_header":"User-Agent","rewrite_value":"","description":""},{"enabled":true,"type":"KEYWORD","action":"REPLACE","match_value":"Mac","rewrite_header":"User-Agent","description":"","rewrite_value":"FFF"},{"enabled":true,"type":"REGEX","action":"REPLACE","match_value":"(Apple|iPhone|iPad|Macintosh|Mac OS X|Mac|Darwin|Microsoft|Windows|Linux|Android|OpenHarmony|HUAWEI|OPPO|Vivo|XiaoMi|Mobile|Dalvik)","rewrite_header":"User-Agent","description":"","rewrite_value":"FFF"},{"enabled":true,"type":"FINAL","action":"REPLACE","match_value":"","rewrite_header":"User-Agent","description":"Default Fallback Rule","rewrite_value":"FFF"}]' \ No newline at end of file diff --git a/openwrt/po/zh_cn/ua3f.po b/openwrt/po/zh_cn/ua3f.po index 5bd5524..02b62d0 100644 --- a/openwrt/po/zh_cn/ua3f.po +++ b/openwrt/po/zh_cn/ua3f.po @@ -126,7 +126,7 @@ msgid "Set TTL" msgstr "固定 TTL" msgid "Set the TTL 64 for packets" -msgstr "固定数据包的 TTL" +msgstr "固定数据包的 TTL 为 64" msgid "Connection Statistics" msgstr "连接实时统计" @@ -257,6 +257,12 @@ msgstr "删除 TCP 时间戳" msgid "Remove TCP Timestamp option" msgstr "移除 TCP 时间戳选项" +msgid "Set TCP Initial Window" +msgstr "固定 TCP 初始接收窗口" + +msgid "Set the TCP Initial Window to 65535 for SYN packets" +msgstr "固定 TCP SYN 的 TCP 初始接收窗口设置为 65535" + msgid "Set IP ID" msgstr "固定 IP ID" diff --git a/src/internal/config/config.go b/src/internal/config/config.go index 7d6f8d4..7dc3255 100644 --- a/src/internal/config/config.go +++ b/src/internal/config/config.go @@ -27,19 +27,20 @@ const ( ) type Config struct { - ServerMode ServerMode - BindAddr string - Port int - ListenAddr string - LogLevel string - RewriteMode RewriteMode - Rules string - PayloadUA string - UARegex string - PartialReplace bool - SetTTL bool - SetIPID bool - DelTCPTimestamp bool + ServerMode ServerMode + BindAddr string + Port int + ListenAddr string + LogLevel string + RewriteMode RewriteMode + Rules string + PayloadUA string + UARegex string + PartialReplace bool + SetTTL bool + SetIPID bool + DelTCPTimestamp bool + SetTCPInitialWindow bool } func Parse() (*Config, bool) { @@ -97,6 +98,9 @@ func Parse() (*Config, bool) { if os.Getenv("UA3F_IPID") == "1" { cfg.SetIPID = true } + if os.Getenv("UA3F_TCP_INIT_WINDOW") == "1" { + cfg.SetTCPInitialWindow = true + } // Parse other options from -o flag opts := strings.Split(others, ",") diff --git a/src/internal/server/netlink/iptables.go b/src/internal/server/netlink/iptables.go index 17a3c03..3bd6f74 100644 --- a/src/internal/server/netlink/iptables.go +++ b/src/internal/server/netlink/iptables.go @@ -22,7 +22,7 @@ var RuleTTL = []string{ "--ttl-set", "64", } -var RuleDelTCPTS = []string{ +var RuleHookTCPSyn = []string{ "-p", "tcp", "--tcp-flags", "SYN", "SYN", "-j", "NFQUEUE", @@ -61,8 +61,8 @@ func (s *Server) iptSetup() error { } } } - if s.cfg.DelTCPTimestamp && !s.cfg.SetIPID { - err = s.IptDelTCPTS(ipt) + if (s.cfg.DelTCPTimestamp || s.cfg.SetTCPInitialWindow) && !s.cfg.SetIPID { + err = s.IptHookTCPSyn(ipt) if err != nil { return err } @@ -83,7 +83,7 @@ func (s *Server) iptCleanup() error { } _ = ipt.DeleteIfExists(table, chain, RuleTTL...) _ = ipt.DeleteIfExists(table, chain, RuleIP...) - _ = ipt.DeleteIfExists(table, chain, RuleDelTCPTS...) + _ = ipt.DeleteIfExists(table, chain, RuleHookTCPSyn...) if s.cfg.SetTTL { _ = s.NftCleanup() } @@ -98,8 +98,8 @@ func (s *Server) IptSetTTL(ipt *iptables.IPTables) error { return nil } -func (s *Server) IptDelTCPTS(ipt *iptables.IPTables) error { - err := ipt.Append(table, chain, RuleDelTCPTS...) +func (s *Server) IptHookTCPSyn(ipt *iptables.IPTables) error { + err := ipt.Append(table, chain, RuleHookTCPSyn...) if err != nil { return err } diff --git a/src/internal/server/netlink/netlink_linux.go b/src/internal/server/netlink/netlink_linux.go index fc62d80..7788bae 100644 --- a/src/internal/server/netlink/netlink_linux.go +++ b/src/internal/server/netlink/netlink_linux.go @@ -45,8 +45,8 @@ func (s *Server) Start() (err error) { slog.Error("s.Firewall.Setup", slog.Any("error", err)) return err } - slog.Info("Packet modification configuration", slog.Bool("ttl", s.cfg.SetTTL), slog.Bool("tcpts", s.cfg.DelTCPTimestamp), slog.Bool("ipid", s.cfg.SetIPID)) - if s.cfg.DelTCPTimestamp || s.cfg.SetIPID { + slog.Info("Packet modification configuration", slog.Bool("ttl", s.cfg.SetTTL), slog.Bool("tcpts", s.cfg.DelTCPTimestamp), slog.Bool("ipid", s.cfg.SetIPID), slog.Bool("tcp_init_window", s.cfg.SetTCPInitialWindow)) + if s.cfg.DelTCPTimestamp || s.cfg.SetTCPInitialWindow || s.cfg.SetIPID { return s.nfqServer.Start() } return nil @@ -63,8 +63,13 @@ func (s *Server) handlePacket(packet *netfilter.Packet) { nf := s.nfqServer.Nf modified := false - if s.cfg.DelTCPTimestamp && packet.TCP != nil { - modified = s.clearTCPTimestamp(packet.TCP) || modified + if packet.TCP != nil { + if s.cfg.DelTCPTimestamp { + modified = s.clearTCPTimestamp(packet.TCP) || modified + } + if s.cfg.SetTCPInitialWindow { + modified = s.setInitialTCPWindow(packet.TCP) || modified + } } if s.cfg.SetIPID { modified = s.zeroIPID(packet) || modified @@ -110,6 +115,18 @@ func (s *Server) clearTCPTimestamp(tcp *layers.TCP) bool { return modified } +// setInitialTCPWindow sets the TCP initial window size to 65535 for SYN packets +func (s *Server) setInitialTCPWindow(tcp *layers.TCP) bool { + if !(tcp.SYN && !tcp.ACK) { + return false + } + if tcp.Window == uint16(65535) { + return false + } + tcp.Window = uint16(65535) + return true +} + // zeroIPID sets the IP ID field to zero for IPv4 packets // Returns true if the packet was modified func (s *Server) zeroIPID(packet *netfilter.Packet) bool { diff --git a/src/internal/server/netlink/nftables.go b/src/internal/server/netlink/nftables.go index 813cec2..b73856c 100644 --- a/src/internal/server/netlink/nftables.go +++ b/src/internal/server/netlink/nftables.go @@ -28,8 +28,8 @@ func (s *Server) nftSetup() error { if s.cfg.SetTTL { s.NftSetTTL(tx, s.Nftable) } - if s.cfg.DelTCPTimestamp && !s.cfg.SetIPID { - s.NftDelTCPTS(tx, s.Nftable) + if (s.cfg.DelTCPTimestamp || s.cfg.SetTCPInitialWindow) && !s.cfg.SetIPID { + s.NftHookTCPSyn(tx, s.Nftable) } if s.cfg.SetIPID { s.NftSetIP(tx, s.Nftable) @@ -112,9 +112,9 @@ func (s *Server) NftSetTTLIngress(nft knftables.Interface, table *knftables.Tabl return nil } -func (s *Server) NftDelTCPTS(tx *knftables.Transaction, table *knftables.Table) { +func (s *Server) NftHookTCPSyn(tx *knftables.Transaction, table *knftables.Table) { chain := &knftables.Chain{ - Name: "DEL_TCPTS", + Name: "HOOK_TCP_SYN", Table: table.Name, Type: knftables.PtrTo(knftables.FilterType), Hook: knftables.PtrTo(knftables.PostroutingHook),