platform: modularize api/gui, add docs-tests-web foundation, and refresh root config
This commit is contained in:
157
selective-vpn-api/app/traffic_mode_iface.go
Normal file
157
selective-vpn-api/app/traffic_mode_iface.go
Normal file
@@ -0,0 +1,157 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
trafficmodepkg "selective-vpn-api/app/trafficmode"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func ensureRoutesTableEntry() {
|
||||
data, _ := os.ReadFile("/etc/iproute2/rt_tables")
|
||||
want := fmt.Sprintf("%s %s", routesTableNum(), routesTableName())
|
||||
if strings.Contains(string(data), "\n"+want) || strings.HasPrefix(string(data), want) {
|
||||
return
|
||||
}
|
||||
f, err := os.OpenFile("/etc/iproute2/rt_tables", os.O_APPEND|os.O_WRONLY, 0o644)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
_, _ = fmt.Fprintf(f, "%s\n", want)
|
||||
}
|
||||
|
||||
func ifaceExists(iface string) bool {
|
||||
return trafficmodepkg.IfaceExists(iface, runCommand)
|
||||
}
|
||||
|
||||
func statusIfaceFromFile() string {
|
||||
data, err := os.ReadFile(statusFilePath)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
var st Status
|
||||
if json.Unmarshal(data, &st) != nil {
|
||||
return ""
|
||||
}
|
||||
return strings.TrimSpace(st.Iface)
|
||||
}
|
||||
|
||||
func listUpIfaces() []string {
|
||||
return trafficmodepkg.ListUpIfaces(runCommand)
|
||||
}
|
||||
|
||||
func listSelectableIfaces(preferred string) []string {
|
||||
return trafficmodepkg.ListSelectableIfaces(listUpIfaces(), preferred)
|
||||
}
|
||||
|
||||
func isVPNLikeIface(iface string) bool {
|
||||
return trafficmodepkg.IsVPNLikeIface(iface)
|
||||
}
|
||||
|
||||
func resolveTrafficIface(preferred string) (string, string) {
|
||||
return trafficmodepkg.ResolveTrafficIface(preferred, ifaceExists, statusIfaceFromFile, listUpIfaces)
|
||||
}
|
||||
|
||||
type autoLocalRoute = trafficmodepkg.AutoLocalRoute
|
||||
|
||||
func parseRouteDevice(fields []string) string {
|
||||
return trafficmodepkg.ParseRouteDevice(fields)
|
||||
}
|
||||
|
||||
func isContainerIface(iface string) bool {
|
||||
return trafficmodepkg.IsContainerIface(iface)
|
||||
}
|
||||
|
||||
func routeLineIsLinkDown(line string) bool {
|
||||
return trafficmodepkg.RouteLineIsLinkDown(line)
|
||||
}
|
||||
|
||||
func isAutoBypassDestination(dst string) bool {
|
||||
return trafficmodepkg.IsAutoBypassDestination(dst)
|
||||
}
|
||||
|
||||
func detectAutoLocalBypassRoutes(vpnIface string) []autoLocalRoute {
|
||||
vpnIface = strings.TrimSpace(vpnIface)
|
||||
out, _, code, _ := runCommand("ip", "-4", "route", "show", "table", "main")
|
||||
if code != 0 {
|
||||
return nil
|
||||
}
|
||||
return trafficmodepkg.ParseAutoBypassRoutes(out, vpnIface, isVPNLikeIface)
|
||||
}
|
||||
|
||||
func applyAutoLocalBypass(vpnIface string) {
|
||||
for _, rt := range detectAutoLocalBypassRoutes(vpnIface) {
|
||||
_, _, _, _ = runCommand(
|
||||
"ip", "-4", "route", "replace",
|
||||
rt.Dst, "dev", rt.Dev, "table", routesTableName(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func ingressBypassConfig() trafficmodepkg.IngressBypassConfig {
|
||||
return trafficmodepkg.IngressBypassConfig{
|
||||
TableName: routesTableName(),
|
||||
PreroutingChain: trafficIngressPreroutingChain,
|
||||
OutputChain: trafficIngressOutputChain,
|
||||
MarkIngress: MARK_INGRESS,
|
||||
CaptureComment: trafficIngressCaptureComment,
|
||||
RestoreComment: trafficIngressRestoreComment,
|
||||
}
|
||||
}
|
||||
|
||||
func ensureIngressReplyBypassChains() {
|
||||
trafficmodepkg.EnsureIngressReplyBypassChains(ingressBypassConfig(), runCommandTimeout)
|
||||
}
|
||||
|
||||
func flushIngressReplyBypassChains() error {
|
||||
return trafficmodepkg.FlushIngressReplyBypassChains(ingressBypassConfig(), runCommandTimeout)
|
||||
}
|
||||
|
||||
func enableIngressReplyBypass(vpnIface string) error {
|
||||
return trafficmodepkg.EnableIngressReplyBypass(ingressBypassConfig(), strings.TrimSpace(vpnIface), runCommandTimeout)
|
||||
}
|
||||
|
||||
func disableIngressReplyBypass() error {
|
||||
return trafficmodepkg.DisableIngressReplyBypass(ingressBypassConfig(), runCommandTimeout)
|
||||
}
|
||||
|
||||
func ingressReplyNftActive() bool {
|
||||
return trafficmodepkg.IngressReplyNftActive(ingressBypassConfig(), runCommandTimeout)
|
||||
}
|
||||
|
||||
func prefStr(v int) string {
|
||||
return trafficmodepkg.PrefStr(v)
|
||||
}
|
||||
|
||||
func trafficModeRulesConfig() trafficmodepkg.RulesConfig {
|
||||
return trafficmodepkg.RulesConfig{
|
||||
RoutesTableName: routesTableName(),
|
||||
Mark: MARK,
|
||||
MarkIngress: MARK_INGRESS,
|
||||
PrefSelective: trafficRulePrefSelective,
|
||||
PrefFull: trafficRulePrefFull,
|
||||
PrefMarkIngressReply: trafficRulePrefMarkIngressReply,
|
||||
ModeFull: string(TrafficModeFullTunnel),
|
||||
ModeSelective: string(TrafficModeSelective),
|
||||
ModeDirect: string(TrafficModeDirect),
|
||||
}
|
||||
}
|
||||
|
||||
func trafficModeOverrideConfig() trafficmodepkg.OverrideConfig {
|
||||
return trafficmodepkg.OverrideConfig{
|
||||
RoutesTableName: routesTableName(),
|
||||
RulePerKindLimit: trafficRulePerKindLimit,
|
||||
PrefManagedMin: trafficRulePrefManagedMin,
|
||||
PrefManagedMax: trafficRulePrefManagedMax,
|
||||
PrefDirectSubnetBase: trafficRulePrefDirectSubnetStart,
|
||||
PrefDirectUIDBase: trafficRulePrefDirectUIDStart,
|
||||
PrefVPNSubnetBase: trafficRulePrefVPNSubnetStart,
|
||||
PrefVPNUIDBase: trafficRulePrefVPNUIDStart,
|
||||
}
|
||||
}
|
||||
|
||||
func removeTrafficRulesForTable() {
|
||||
trafficmodepkg.RemoveRulesForTable(trafficModeOverrideConfig(), runCommand)
|
||||
}
|
||||
Reference in New Issue
Block a user