// Package firewall generates an nftables ruleset preview for a WireGuard // server. It never touches the live firewall - the output is text only, // meant to be reviewed and applied manually (nft -f ) or copied into // an existing ruleset. package firewall import ( "fmt" "strings" "github.com/ngoduykhanh/wireguard-ui/model" ) // GeneratePreview renders an nftables ruleset snippet for the given server. // If settings.LanInterface is empty, only WireGuard-interface-local traffic // rules are emitted; forwarding to a LAN interface is added when set. func GeneratePreview(server model.Server, settings model.ServerSetting) string { ifaceName := "wgX" listenPort := 0 if server.Interface != nil { if server.Interface.Name != "" { ifaceName = server.Interface.Name } listenPort = server.Interface.ListenPort } var b strings.Builder fmt.Fprintf(&b, "# nftables ruleset preview for server %q (%s)\n", server.Name, server.ID) fmt.Fprintf(&b, "# Generated by wireguard-ui-multi - review before applying, e.g.:\n") fmt.Fprintf(&b, "# nft -f this-file.nft\n") fmt.Fprintf(&b, "# Not applied automatically.\n\n") fmt.Fprintf(&b, "table inet wireguard_ui_%s {\n", server.ID) fmt.Fprintf(&b, " chain input {\n") fmt.Fprintf(&b, " type filter hook input priority 0; policy accept;\n") fmt.Fprintf(&b, " udp dport %d accept comment \"wg-ui-multi: %s\"\n", listenPort, server.ID) fmt.Fprintf(&b, " }\n\n") fmt.Fprintf(&b, " chain forward {\n") fmt.Fprintf(&b, " type filter hook forward priority 0; policy accept;\n") fmt.Fprintf(&b, " iifname \"%s\" accept comment \"wg-ui-multi: %s inbound\"\n", ifaceName, server.ID) fmt.Fprintf(&b, " oifname \"%s\" accept comment \"wg-ui-multi: %s outbound\"\n", ifaceName, server.ID) if settings.LanInterface != "" { fmt.Fprintf(&b, " iifname \"%s\" oifname \"%s\" accept comment \"wg-ui-multi: %s -> lan\"\n", ifaceName, settings.LanInterface, server.ID) fmt.Fprintf(&b, " iifname \"%s\" oifname \"%s\" accept comment \"wg-ui-multi: lan -> %s\"\n", settings.LanInterface, ifaceName, server.ID) } fmt.Fprintf(&b, " }\n") fmt.Fprintf(&b, "}\n") if settings.LanInterface == "" { fmt.Fprintf(&b, "\n# No LAN interface configured for this server - peers can only reach\n") fmt.Fprintf(&b, "# each other, not your LAN. Set one in Server Settings to add forwarding.\n") } return b.String() }