我正在尝试从沙盒应用程序中检测 macOS 中的 VPN 连接是否处于活动状态,但很难找到适用于各种 VPN 服务的通用解决方案。目前,我正在使用 2 种方法(见下文),但这些方法似乎对所有 VPN 服务/客户端都不可靠。
以下方法适用于 Cisco AnyConnect 客户端和我的 VPN 服务,但对于其他 VPN 客户端/服务,例如 Viscosity(可能还有其他 OpenVPN 客户端),这些方法根本不起作用。在比较从非活动-VPN-connection 到活动-VPN-connection 的值时,在 DNS 服务器或主要服务值中未检测到任何更改。
我还应该提到我已经看过这篇文章,并且认为这不是这个特定用例的好解决方案。我不想假设对于每一个 VPN 服务来说,它总是一个只有在 VPN 连接处于活动状态时才可用的主机。
任何指导将不胜感激。先感谢您。
1)查看当前的 DNS 服务器(取自此处)
- (NSString *)getDNSAddressesCSV
{
NSMutableArray *addresses = [NSMutableArray new];
union res_sockaddr_union servers[NI_MAXSERV];
int serversFound = res_9_getservers(_state, servers, NI_MAXSERV);
char hostBuffer[NI_MAXHOST];
for (int i = 0; i < serversFound; i ++)
{
union res_sockaddr_union s = servers[i];
if (s.sin.sin_len > 0)
{
if (EXIT_SUCCESS == getnameinfo((struct sockaddr *)&s.sin, // Pointer to your struct sockaddr
(socklen_t)s.sin.sin_len, // Size of this struct
(char *)&hostBuffer, // Pointer to hostname string
sizeof(hostBuffer), // Size of this string
nil, // Pointer to service name string
0,
NI_NUMERICHOST))
{ // Flags given
[addresses addObject:[NSString stringWithUTF8String:hostBuffer]];
}
}
}
return [addresses componentsJoinedByString:@","];
}
和 2) 从SCDynamicStore
获取当前的主要服务(取自这里)
- (NSString *) getVPNService
{
SCDynamicStoreRef dynamicStoreDomainState = SCDynamicStoreCreate(NULL,
CFSTR("appNameGoesHere"),
NULL,
NULL);
if (dynamicStoreDomainState)
{
NSString *netIPv4Key = [NSString stringWithFormat:@"%@/%@/%@/%@",
kSCDynamicStoreDomainState,
kSCCompNetwork,
kSCCompGlobal,
kSCEntNetIPv4];
NSMutableDictionary *netIPv4Dictionary = (NSMutableDictionary *) CFBridgingRelease(SCDynamicStoreCopyValue(dynamicStoreDomainState, (CFStringRef)netIPv4Key));
if (netIPv4Dictionary )
{
NSString *primaryService = [netIPv4Dictionary objectForKey:(NSString *)kSCDynamicStorePropNetPrimaryService];
if (primaryService)
{
CFRelease(dynamicStoreDomainState);
CFRelease((__bridge CFTypeRef)(netIPv4Key));
return primaryService;
}
else
{
CFRelease(dynamicStoreDomainState);
CFRelease((__bridge CFTypeRef)(netIPv4Key));
return @"";
}
}
CFRelease(dynamicStoreDomainState);
}
return @"";
}