91 lines
2.4 KiB
Go
91 lines
2.4 KiB
Go
package app
|
|
|
|
import (
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func transportEnsureNetnsNAT(spec transportNetnsSpec) error {
|
|
_ = transportRunSoft(4*time.Second, "nft", "add", "table", "ip", transportNetnsNATTable)
|
|
_ = transportRunSoft(
|
|
4*time.Second,
|
|
"nft", "add", "chain", "ip", transportNetnsNATTable, "postrouting",
|
|
"{", "type", "nat", "hook", "postrouting", "priority", "srcnat;", "policy", "accept;", "}",
|
|
)
|
|
|
|
if err := transportNetnsDeleteNATRule(spec.Name); err != nil {
|
|
return err
|
|
}
|
|
tag := transportNetnsNATCommentTag(spec.Name)
|
|
return transportRunMust(
|
|
4*time.Second,
|
|
"nft", "add", "rule", "ip", transportNetnsNATTable, "postrouting",
|
|
"ip", "saddr", spec.Prefix.String(),
|
|
"oifname", spec.Uplink,
|
|
"masquerade",
|
|
"comment", tag,
|
|
)
|
|
}
|
|
|
|
func transportNetnsDeleteNATRule(nsName string) error {
|
|
stdout, stderr, code, err := transportRunCommand(4*time.Second, "nft", "-a", "list", "chain", "ip", transportNetnsNATTable, "postrouting")
|
|
if err != nil || code != 0 {
|
|
if strings.Contains(strings.ToLower(strings.TrimSpace(stderr+" "+stdout)), "no such file") {
|
|
return nil
|
|
}
|
|
return transportCommandError("nft -a list chain ip "+transportNetnsNATTable+" postrouting", stdout, stderr, code, err)
|
|
}
|
|
tag := `comment "` + transportNetnsNATCommentTag(nsName) + `"`
|
|
legacyTag := `comment "svpn_netns:` + nsName + `"`
|
|
for _, line := range strings.Split(stdout, "\n") {
|
|
if !strings.Contains(line, tag) && !strings.Contains(line, legacyTag) {
|
|
continue
|
|
}
|
|
h := parseNftHandle(line)
|
|
if h <= 0 {
|
|
continue
|
|
}
|
|
_ = transportRunSoft(3*time.Second, "nft", "delete", "rule", "ip", transportNetnsNATTable, "postrouting", "handle", strconv.Itoa(h))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func transportEnsureNetnsPolicyRoute(spec transportNetnsSpec) error {
|
|
table := strings.TrimSpace(routesTableName())
|
|
if table == "" {
|
|
return nil
|
|
}
|
|
return transportRunMust(
|
|
4*time.Second,
|
|
"ip", "-4", "route", "replace",
|
|
spec.Prefix.String(),
|
|
"dev", spec.HostVeth,
|
|
"table", table,
|
|
)
|
|
}
|
|
|
|
func transportDeleteNetnsPolicyRoute(spec transportNetnsSpec) error {
|
|
table := strings.TrimSpace(routesTableName())
|
|
if table == "" {
|
|
return nil
|
|
}
|
|
if err := transportRunSoft(
|
|
4*time.Second,
|
|
"ip", "-4", "route", "del",
|
|
spec.Prefix.String(),
|
|
"table", table,
|
|
); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func transportNetnsNATCommentTag(nsName string) string {
|
|
base := sanitizeID(strings.TrimSpace(nsName))
|
|
if base == "" {
|
|
base = "ns"
|
|
}
|
|
return "svpn_netns_" + base
|
|
}
|