New firewall package generates an nftables snippet (INPUT accept for the listen port, FORWARD rules for the WireGuard interface, optional LAN forwarding via a new ServerSetting.LanInterface field). Text only - nothing is applied to the live firewall. Exposed as GET /servers/:id/firewall-preview and a "Firewall Preview" button in the All Servers page. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
57 lines
2.4 KiB
Go
57 lines
2.4 KiB
Go
// 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 <file>) 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()
|
|
}
|