158 lines
4.5 KiB
Go
158 lines
4.5 KiB
Go
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)
|
|
}
|