138 lines
4.3 KiB
Go
138 lines
4.3 KiB
Go
package app
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
trafficmodepkg "selective-vpn-api/app/trafficmode"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func normalizeTrafficMode(raw TrafficMode) TrafficMode {
|
|
switch strings.ToLower(strings.TrimSpace(string(raw))) {
|
|
case string(TrafficModeFullTunnel):
|
|
return TrafficModeFullTunnel
|
|
case string(TrafficModeDirect):
|
|
return TrafficModeDirect
|
|
case string(TrafficModeSelective):
|
|
return TrafficModeSelective
|
|
default:
|
|
return TrafficModeSelective
|
|
}
|
|
}
|
|
|
|
func normalizePreferredIface(raw string) string {
|
|
return trafficmodepkg.NormalizePreferredIface(raw)
|
|
}
|
|
|
|
func tokenizeList(raw []string) []string {
|
|
return trafficmodepkg.TokenizeList(raw)
|
|
}
|
|
|
|
func normalizeSubnetList(raw []string) []string {
|
|
return trafficmodepkg.NormalizeSubnetList(raw)
|
|
}
|
|
|
|
func normalizeUIDToken(tok string) (string, bool) {
|
|
return trafficmodepkg.NormalizeUIDToken(tok)
|
|
}
|
|
|
|
func normalizeUIDList(raw []string) []string {
|
|
return trafficmodepkg.NormalizeUIDList(raw)
|
|
}
|
|
|
|
func normalizeCgroupList(raw []string) []string {
|
|
return trafficmodepkg.NormalizeCgroupList(raw)
|
|
}
|
|
|
|
func normalizeTrafficModeState(st TrafficModeState) TrafficModeState {
|
|
st.Mode = normalizeTrafficMode(st.Mode)
|
|
st.PreferredIface = normalizePreferredIface(st.PreferredIface)
|
|
st.ForceVPNSubnets = normalizeSubnetList(st.ForceVPNSubnets)
|
|
st.ForceVPNUIDs = normalizeUIDList(st.ForceVPNUIDs)
|
|
st.ForceVPNCGroups = normalizeCgroupList(st.ForceVPNCGroups)
|
|
st.ForceDirectSubnets = normalizeSubnetList(st.ForceDirectSubnets)
|
|
st.ForceDirectUIDs = normalizeUIDList(st.ForceDirectUIDs)
|
|
st.ForceDirectCGroups = normalizeCgroupList(st.ForceDirectCGroups)
|
|
return st
|
|
}
|
|
|
|
func loadTrafficModeState() TrafficModeState {
|
|
data, err := os.ReadFile(trafficModePath)
|
|
if err != nil {
|
|
return inferTrafficModeState()
|
|
}
|
|
|
|
type diskState struct {
|
|
Mode TrafficMode `json:"mode"`
|
|
PreferredIface string `json:"preferred_iface,omitempty"`
|
|
AutoLocalBypass *bool `json:"auto_local_bypass,omitempty"`
|
|
IngressReplyBypass *bool `json:"ingress_reply_bypass,omitempty"`
|
|
ForceVPNSubnets []string `json:"force_vpn_subnets,omitempty"`
|
|
ForceVPNUIDs []string `json:"force_vpn_uids,omitempty"`
|
|
ForceVPNCGroups []string `json:"force_vpn_cgroups,omitempty"`
|
|
ForceDirectSubnets []string `json:"force_direct_subnets,omitempty"`
|
|
ForceDirectUIDs []string `json:"force_direct_uids,omitempty"`
|
|
ForceDirectCGroups []string `json:"force_direct_cgroups,omitempty"`
|
|
}
|
|
var raw diskState
|
|
if err := json.Unmarshal(data, &raw); err != nil {
|
|
return inferTrafficModeState()
|
|
}
|
|
st := TrafficModeState{
|
|
Mode: raw.Mode,
|
|
PreferredIface: raw.PreferredIface,
|
|
AutoLocalBypass: trafficAutoLocalDefault,
|
|
IngressReplyBypass: trafficIngressReplyDefault,
|
|
ForceVPNSubnets: append([]string(nil), raw.ForceVPNSubnets...),
|
|
ForceVPNUIDs: append([]string(nil), raw.ForceVPNUIDs...),
|
|
ForceVPNCGroups: append([]string(nil), raw.ForceVPNCGroups...),
|
|
ForceDirectSubnets: append([]string(nil), raw.ForceDirectSubnets...),
|
|
ForceDirectUIDs: append([]string(nil), raw.ForceDirectUIDs...),
|
|
ForceDirectCGroups: append([]string(nil), raw.ForceDirectCGroups...),
|
|
}
|
|
if raw.AutoLocalBypass != nil {
|
|
st.AutoLocalBypass = *raw.AutoLocalBypass
|
|
}
|
|
if raw.IngressReplyBypass != nil {
|
|
st.IngressReplyBypass = *raw.IngressReplyBypass
|
|
}
|
|
return normalizeTrafficModeState(st)
|
|
}
|
|
|
|
func saveTrafficModeState(st TrafficModeState) error {
|
|
st = normalizeTrafficModeState(st)
|
|
st.UpdatedAt = time.Now().UTC().Format(time.RFC3339)
|
|
|
|
data, err := json.MarshalIndent(st, "", " ")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := os.MkdirAll(stateDir, 0o755); err != nil {
|
|
return err
|
|
}
|
|
tmp := trafficModePath + ".tmp"
|
|
if err := os.WriteFile(tmp, data, 0o644); err != nil {
|
|
return err
|
|
}
|
|
return os.Rename(tmp, trafficModePath)
|
|
}
|
|
|
|
func inferTrafficModeState() TrafficModeState {
|
|
rules := readTrafficRules()
|
|
mode := detectAppliedTrafficMode(rules)
|
|
iface, _ := resolveTrafficIface("")
|
|
return normalizeTrafficModeState(TrafficModeState{
|
|
Mode: mode,
|
|
PreferredIface: iface,
|
|
AutoLocalBypass: trafficAutoLocalDefault,
|
|
IngressReplyBypass: trafficIngressReplyDefault,
|
|
ForceVPNSubnets: nil,
|
|
ForceVPNUIDs: nil,
|
|
ForceVPNCGroups: nil,
|
|
ForceDirectSubnets: nil,
|
|
ForceDirectUIDs: nil,
|
|
ForceDirectCGroups: nil,
|
|
})
|
|
}
|