我正在尝试为基于 Android 的应用程序构建一个 VPN 客户端移动设备,这些应用程序通过 VPN 隧道连接到虚拟基础设施。我有一个类似的 Linux/Windows 应用程序,我知道如何打开 tun/tap 设备(打开 /dev/net/tun)。我们如何使用 C 为 Android 做同样的事情?
另外,android.net API 中的 VpnService 类究竟做了什么?
我正在尝试为基于 Android 的应用程序构建一个 VPN 客户端移动设备,这些应用程序通过 VPN 隧道连接到虚拟基础设施。我有一个类似的 Linux/Windows 应用程序,我知道如何打开 tun/tap 设备(打开 /dev/net/tun)。我们如何使用 C 为 Android 做同样的事情?
另外,android.net API 中的 VpnService 类究竟做了什么?
如果您仍然想在 android - native C 上打开隧道,我建议您看看 android 本身如何打开它(来自文件:services/jni/com_android_server_connectivity_Vpn.cpp)
static int create_interface(int mtu)
{
int tun = open("/dev/tun", O_RDWR | O_NONBLOCK);
ifreq ifr4;
memset(&ifr4, 0, sizeof(ifr4));
// Allocate interface.
ifr4.ifr_flags = IFF_TUN | IFF_NO_PI;
if (ioctl(tun, TUNSETIFF, &ifr4)) {
ALOGE("Cannot allocate TUN: %s", strerror(errno));
goto error;
}
// Activate interface.
ifr4.ifr_flags = IFF_UP;
if (ioctl(inet4, SIOCSIFFLAGS, &ifr4)) {
ALOGE("Cannot activate %s: %s", ifr4.ifr_name, strerror(errno));
goto error;
}
// Set MTU if it is specified.
ifr4.ifr_mtu = mtu;
if (mtu > 0 && ioctl(inet4, SIOCSIFMTU, &ifr4)) {
ALOGE("Cannot set MTU on %s: %s", ifr4.ifr_name, strerror(errno));
goto error;
}
return tun;
error:
close(tun);
return SYSTEM_ERROR;
}
VpnService 类正是您所需要的。它提供对 tun 设备的访问。如果没有 root 权限,您无法直接打开 /dev/net/tun。请参阅 ToyVPN 示例项目或 OpenVPN for Android 等开源 VPN 项目。
您需要root
在 Android 上打开 tuntap。
this->_handle = open("/dev/tun", O_RDWR | O_NONBLOCK | O_CLOEXEC);
if (this->_handle < 0) {
this->_handle = open("/dev/net/tun", O_RDWR | O_NONBLOCK | O_CLOEXEC);
}
补充:
/dev/tun
两者/dev/net/tun
都需要尝试打开设备。Android 的发行版太多了,每个发行版都有各自的变化,而且 tuntap 设备也略有不同。
本机代码可能不是打开 tuntap 的好主意!