platform: modularize api/gui, add docs-tests-web foundation, and refresh root config
This commit is contained in:
95
selective-vpn-api/app/egress_identity_providers.go
Normal file
95
selective-vpn-api/app/egress_identity_providers.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (egressSystemProvider) Probe(_ egressScopeTarget) (string, error) {
|
||||
return egressProbeExternalIP()
|
||||
}
|
||||
|
||||
func (egressAdGuardProvider) Probe(_ egressScopeTarget) (string, error) {
|
||||
stdout, stderr, code, err := runCommandTimeout(2*time.Second, "systemctl", "is-active", adgvpnUnit)
|
||||
state := strings.ToLower(strings.TrimSpace(stdout))
|
||||
if state != "active" || err != nil || code != 0 {
|
||||
return "", transportCommandError("systemctl is-active "+adgvpnUnit, stdout, stderr, code, err)
|
||||
}
|
||||
|
||||
iface, _ := resolveTrafficIface(loadTrafficModeState().PreferredIface)
|
||||
if iface = strings.TrimSpace(iface); iface == "" {
|
||||
return "", fmt.Errorf("adguardvpn interface is not resolved")
|
||||
}
|
||||
if !ifaceExists(iface) {
|
||||
return "", fmt.Errorf("adguardvpn interface %q is not available", iface)
|
||||
}
|
||||
return egressProbeExternalIPViaInterface(iface)
|
||||
}
|
||||
|
||||
func (egressTransportProvider) Probe(target egressScopeTarget) (string, error) {
|
||||
id := sanitizeID(target.SourceID)
|
||||
if id == "" {
|
||||
return "", fmt.Errorf("invalid transport source id")
|
||||
}
|
||||
|
||||
transportMu.Lock()
|
||||
st := loadTransportClientsState()
|
||||
idx := findTransportClientIndex(st.Items, id)
|
||||
var client TransportClient
|
||||
if idx >= 0 {
|
||||
client = st.Items[idx]
|
||||
}
|
||||
transportMu.Unlock()
|
||||
|
||||
if idx < 0 {
|
||||
return "", fmt.Errorf("transport client %q not found", id)
|
||||
}
|
||||
if !client.Enabled {
|
||||
return "", fmt.Errorf("transport client %q is disabled", id)
|
||||
}
|
||||
if normalizeTransportStatus(client.Status) == TransportClientDown {
|
||||
backend := selectTransportBackend(client)
|
||||
live := backend.Health(client)
|
||||
if normalizeTransportStatus(live.Status) != TransportClientUp {
|
||||
msg := strings.TrimSpace(live.Message)
|
||||
if msg == "" {
|
||||
msg = fmt.Sprintf("transport client %q is down", id)
|
||||
}
|
||||
return "", fmt.Errorf("%s", msg)
|
||||
}
|
||||
client.Status = TransportClientUp
|
||||
}
|
||||
|
||||
if transportNetnsEnabled(client) {
|
||||
ns := transportNetnsName(client)
|
||||
if strings.TrimSpace(ns) == "" {
|
||||
return "", fmt.Errorf("transport client %q netns is enabled but netns_name is empty", id)
|
||||
}
|
||||
if client.Kind == TransportClientSingBox {
|
||||
proxyURL := egressSingBoxSOCKSProxyURL(client)
|
||||
if proxyURL == "" {
|
||||
return "", fmt.Errorf("proxy probe failed: singbox socks inbound not found")
|
||||
}
|
||||
// For SingBox in netns we must use tunnel egress probe (SOCKS inbound -> outbound proxy).
|
||||
// Direct netns probe is intentionally not used: in selective mode it may return AdGuard/system IP.
|
||||
ip, err := egressProbeExternalIPInNetnsViaProxy(client, ns, proxyURL)
|
||||
if err == nil {
|
||||
return ip, nil
|
||||
}
|
||||
return "", fmt.Errorf("proxy probe failed: %v", err)
|
||||
}
|
||||
|
||||
ip, err := egressProbeExternalIPInNetns(client, ns)
|
||||
if err == nil {
|
||||
return ip, nil
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
|
||||
iface := strings.TrimSpace(client.Iface)
|
||||
if iface != "" && ifaceExists(iface) {
|
||||
return egressProbeExternalIPViaInterface(iface)
|
||||
}
|
||||
return egressProbeExternalIP()
|
||||
}
|
||||
Reference in New Issue
Block a user