package main import ( "context" "errors" "net" "net/netip" "strings" "time" ) func resolveEndpoint(raw string) (netip.Addr, string, error) { host, port, err := net.SplitHostPort(raw) if err != nil || host == "" || port == "" { return netip.Addr{}, "", errors.New("VPN 公网端点格式无效") } if ip, err := netip.ParseAddr(host); err == nil { if !ip.Is4() || !ip.IsGlobalUnicast() { return netip.Addr{}, "", errors.New("VPN 公网端点需要有效 IPv4 地址") } return ip, port, nil } ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() addresses, err := net.DefaultResolver.LookupNetIP(ctx, "ip4", host) if err != nil { return netip.Addr{}, "", errors.New("无法在连接前解析 VPN 公网端点") } for _, address := range addresses { if address.Is4() && address.IsGlobalUnicast() { return address, port, nil } } return netip.Addr{}, "", errors.New("VPN 公网端点没有可用 IPv4 地址") } // networkPlan contains only public addressing information. The privileged // network adapter still needs to discover the physical gateway and persist a // rollback journal before applying any of these routes. type networkPlan struct { Interface string `json:"interface"` ClientAddress netip.Prefix `json:"client_address"` Routes []netip.Prefix `json:"routes"` Endpoint netip.Addr `json:"endpoint"` EndpointBypass bool `json:"endpoint_bypass"` PhysicalExit *physicalRoute `json:"physical_exit,omitempty"` } type physicalRoute struct { Interface string `json:"interface"` Gateway *netip.Addr `json:"gateway,omitempty"` } // macOS route -n get output is only an observation, never an executable // command. Reject another VPN's utun as the physical endpoint exit. func parsePhysicalRoute(output string) (physicalRoute, error) { var exit physicalRoute for _, line := range strings.Split(output, "\n") { key, value, ok := strings.Cut(strings.TrimSpace(line), ":") if !ok { continue } value = strings.TrimSpace(value) switch key { case "interface": exit.Interface = value case "gateway": gateway, err := netip.ParseAddr(value) if err != nil || !gateway.Is4() || gateway.IsUnspecified() || gateway.IsLoopback() { return physicalRoute{}, errors.New("物理网关地址无效") } exit.Gateway = &gateway } } if len(exit.Interface) < 2 || len(exit.Interface) > 16 || strings.HasPrefix(exit.Interface, "utun") || exit.Interface == "lo0" { return physicalRoute{}, errors.New("VPN 网关当前未经过物理网络出口") } for _, char := range exit.Interface { if !((char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z') || (char >= '0' && char <= '9')) { return physicalRoute{}, errors.New("物理出口接口名称无效") } } return exit, nil } func planNativeRoutes(r *record, interfaceName string, endpoint netip.Addr) (networkPlan, error) { if !strings.HasPrefix(interfaceName, "utun") || len(interfaceName) < 5 { return networkPlan{}, errors.New("本机接口名称无效") } for _, digit := range interfaceName[4:] { if digit < '0' || digit > '9' { return networkPlan{}, errors.New("本机接口名称无效") } } address, err := netip.ParsePrefix(r.Config.ClientAddress) if err != nil || !address.Addr().Is4() || address.Addr().IsUnspecified() { return networkPlan{}, errors.New("本机 IPv4 地址无效") } if !endpoint.IsValid() || !endpoint.Is4() || !endpoint.IsGlobalUnicast() { return networkPlan{}, errors.New("VPN 公网端点必须解析为可达的 IPv4 地址") } plan := networkPlan{Interface: interfaceName, ClientAddress: address, Endpoint: endpoint, Routes: []netip.Prefix{}} seen := make(map[netip.Prefix]bool) for _, part := range strings.Split(r.Config.AllowedIPs, ",") { prefix, err := netip.ParsePrefix(strings.TrimSpace(part)) if err != nil { return networkPlan{}, errors.New("WireGuard 授权路由无效") } if !prefix.Addr().Is4() { return networkPlan{}, errors.New("IPv6 系统路由尚未实现,请在专线中仅授权 IPv4 路由") } prefix = prefix.Masked() if prefix.Bits() == 0 { // These /1 routes override the physical default while retaining it // for explicit endpoint /32 bypass. The helper must install the bypass. for _, half := range []string{"0.0.0.0/1", "128.0.0.0/1"} { p := netip.MustParsePrefix(half) if !seen[p] { plan.Routes = append(plan.Routes, p) seen[p] = true } } plan.EndpointBypass = true continue } if !seen[prefix] { plan.Routes = append(plan.Routes, prefix) seen[prefix] = true } if prefix.Contains(endpoint) { plan.EndpointBypass = true } } if plan.EndpointBypass { // A physical /32 must be installed before any matching VPN route. // Otherwise a full-tunnel VPN can attempt to reach itself through TUN. if endpoint == address.Addr() { return networkPlan{}, errors.New("VPN 端点与本机地址冲突") } } return plan, nil }