Add test for dropping packets to VPN address from non VPN-interface
Bug: 295800201 Test: HostsideVpnTests Change-Id: I0785ee1562fa50c1b6a4aca9ac077ad753cc2700
This commit is contained in:
parent
b4772b1e5d
commit
ffa2bce381
2 changed files with 102 additions and 50 deletions
|
|
@ -24,6 +24,7 @@ import static android.content.pm.PackageManager.FEATURE_TELEPHONY;
|
|||
import static android.content.pm.PackageManager.FEATURE_WIFI;
|
||||
import static android.net.ConnectivityManager.TYPE_VPN;
|
||||
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
|
||||
import static android.net.NetworkCapabilities.TRANSPORT_TEST;
|
||||
import static android.os.Process.INVALID_UID;
|
||||
import static android.system.OsConstants.AF_INET;
|
||||
import static android.system.OsConstants.AF_INET6;
|
||||
|
|
@ -72,6 +73,7 @@ import android.content.pm.PackageManager;
|
|||
import android.database.Cursor;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.ConnectivityManager.NetworkCallback;
|
||||
import android.net.InetAddresses;
|
||||
import android.net.IpSecManager;
|
||||
import android.net.LinkAddress;
|
||||
import android.net.LinkProperties;
|
||||
|
|
@ -91,6 +93,7 @@ import android.net.VpnTransportInfo;
|
|||
import android.net.cts.util.CtsNetUtils;
|
||||
import android.net.util.KeepaliveUtils;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
|
@ -249,6 +252,7 @@ public class VpnTest {
|
|||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
assumeTrue(supportedHardware());
|
||||
mNetwork = null;
|
||||
mTestContext = getInstrumentation().getContext();
|
||||
mTargetContext = getInstrumentation().getTargetContext();
|
||||
|
|
@ -879,7 +883,6 @@ public class VpnTest {
|
|||
|
||||
@Test @IgnoreUpTo(SC_V2) // TODO: Use to Build.VERSION_CODES.SC_V2 when available
|
||||
public void testChangeUnderlyingNetworks() throws Exception {
|
||||
assumeTrue(supportedHardware());
|
||||
assumeTrue(mPackageManager.hasSystemFeature(FEATURE_WIFI));
|
||||
assumeTrue(mPackageManager.hasSystemFeature(FEATURE_TELEPHONY));
|
||||
final TestableNetworkCallback callback = new TestableNetworkCallback();
|
||||
|
|
@ -938,7 +941,6 @@ public class VpnTest {
|
|||
|
||||
@Test
|
||||
public void testDefault() throws Exception {
|
||||
assumeTrue(supportedHardware());
|
||||
if (!SdkLevel.isAtLeastS() && (
|
||||
SystemProperties.getInt("persist.adb.tcp.port", -1) > -1
|
||||
|| SystemProperties.getInt("service.adb.tcp.port", -1) > -1)) {
|
||||
|
|
@ -1033,8 +1035,6 @@ public class VpnTest {
|
|||
|
||||
@Test
|
||||
public void testAppAllowed() throws Exception {
|
||||
assumeTrue(supportedHardware());
|
||||
|
||||
FileDescriptor fd = openSocketFdInOtherApp(TEST_HOST, 80, TIMEOUT_MS);
|
||||
|
||||
// Shell app must not be put in here or it would kill the ADB-over-network use case
|
||||
|
|
@ -1142,8 +1142,6 @@ public class VpnTest {
|
|||
}
|
||||
|
||||
private void doTestAutomaticOnOffKeepaliveMode(final boolean closeSocket) throws Exception {
|
||||
assumeTrue(supportedHardware());
|
||||
|
||||
// Get default network first before starting VPN
|
||||
final Network defaultNetwork = mCM.getActiveNetwork();
|
||||
final TestableNetworkCallback cb = new TestableNetworkCallback();
|
||||
|
|
@ -1231,8 +1229,6 @@ public class VpnTest {
|
|||
|
||||
@Test
|
||||
public void testAppDisallowed() throws Exception {
|
||||
assumeTrue(supportedHardware());
|
||||
|
||||
FileDescriptor localFd = openSocketFd(TEST_HOST, 80, TIMEOUT_MS);
|
||||
FileDescriptor remoteFd = openSocketFdInOtherApp(TEST_HOST, 80, TIMEOUT_MS);
|
||||
|
||||
|
|
@ -1265,8 +1261,6 @@ public class VpnTest {
|
|||
|
||||
@Test
|
||||
public void testSocketClosed() throws Exception {
|
||||
assumeTrue(supportedHardware());
|
||||
|
||||
final FileDescriptor localFd = openSocketFd(TEST_HOST, 80, TIMEOUT_MS);
|
||||
final List<FileDescriptor> remoteFds = new ArrayList<>();
|
||||
|
||||
|
|
@ -1290,7 +1284,6 @@ public class VpnTest {
|
|||
|
||||
@Test
|
||||
public void testExcludedRoutes() throws Exception {
|
||||
assumeTrue(supportedHardware());
|
||||
assumeTrue(SdkLevel.isAtLeastT());
|
||||
|
||||
// Shell app must not be put in here or it would kill the ADB-over-network use case
|
||||
|
|
@ -1311,8 +1304,6 @@ public class VpnTest {
|
|||
|
||||
@Test
|
||||
public void testIncludedRoutes() throws Exception {
|
||||
assumeTrue(supportedHardware());
|
||||
|
||||
// Shell app must not be put in here or it would kill the ADB-over-network use case
|
||||
String allowedApps = mRemoteSocketFactoryClient.getPackageName() + "," + mPackageName;
|
||||
startVpn(new String[]{"192.0.2.2/32", "2001:db8:1:2::ffe/128"} /* addresses */,
|
||||
|
|
@ -1330,7 +1321,6 @@ public class VpnTest {
|
|||
|
||||
@Test
|
||||
public void testInterleavedRoutes() throws Exception {
|
||||
assumeTrue(supportedHardware());
|
||||
assumeTrue(SdkLevel.isAtLeastT());
|
||||
|
||||
// Shell app must not be put in here or it would kill the ADB-over-network use case
|
||||
|
|
@ -1358,8 +1348,6 @@ public class VpnTest {
|
|||
|
||||
@Test
|
||||
public void testGetConnectionOwnerUidSecurity() throws Exception {
|
||||
assumeTrue(supportedHardware());
|
||||
|
||||
DatagramSocket s;
|
||||
InetAddress address = InetAddress.getByName("localhost");
|
||||
s = new DatagramSocket();
|
||||
|
|
@ -1380,7 +1368,6 @@ public class VpnTest {
|
|||
|
||||
@Test
|
||||
public void testSetProxy() throws Exception {
|
||||
assumeTrue(supportedHardware());
|
||||
ProxyInfo initialProxy = mCM.getDefaultProxy();
|
||||
// Receiver for the proxy change broadcast.
|
||||
BlockingBroadcastReceiver proxyBroadcastReceiver = new ProxyChangeBroadcastReceiver();
|
||||
|
|
@ -1420,7 +1407,6 @@ public class VpnTest {
|
|||
|
||||
@Test
|
||||
public void testSetProxyDisallowedApps() throws Exception {
|
||||
assumeTrue(supportedHardware());
|
||||
ProxyInfo initialProxy = mCM.getDefaultProxy();
|
||||
|
||||
String disallowedApps = mPackageName;
|
||||
|
|
@ -1446,7 +1432,6 @@ public class VpnTest {
|
|||
|
||||
@Test
|
||||
public void testNoProxy() throws Exception {
|
||||
assumeTrue(supportedHardware());
|
||||
ProxyInfo initialProxy = mCM.getDefaultProxy();
|
||||
BlockingBroadcastReceiver proxyBroadcastReceiver = new ProxyChangeBroadcastReceiver();
|
||||
proxyBroadcastReceiver.register();
|
||||
|
|
@ -1481,7 +1466,6 @@ public class VpnTest {
|
|||
|
||||
@Test
|
||||
public void testBindToNetworkWithProxy() throws Exception {
|
||||
assumeTrue(supportedHardware());
|
||||
String allowedApps = mPackageName;
|
||||
Network initialNetwork = mCM.getActiveNetwork();
|
||||
ProxyInfo initialProxy = mCM.getDefaultProxy();
|
||||
|
|
@ -1506,9 +1490,6 @@ public class VpnTest {
|
|||
|
||||
@Test
|
||||
public void testVpnMeterednessWithNoUnderlyingNetwork() throws Exception {
|
||||
if (!supportedHardware()) {
|
||||
return;
|
||||
}
|
||||
// VPN is not routing any traffic i.e. its underlying networks is an empty array.
|
||||
ArrayList<Network> underlyingNetworks = new ArrayList<>();
|
||||
String allowedApps = mPackageName;
|
||||
|
|
@ -1538,9 +1519,6 @@ public class VpnTest {
|
|||
|
||||
@Test
|
||||
public void testVpnMeterednessWithNullUnderlyingNetwork() throws Exception {
|
||||
if (!supportedHardware()) {
|
||||
return;
|
||||
}
|
||||
Network underlyingNetwork = mCM.getActiveNetwork();
|
||||
if (underlyingNetwork == null) {
|
||||
Log.i(TAG, "testVpnMeterednessWithNullUnderlyingNetwork cannot execute"
|
||||
|
|
@ -1567,9 +1545,6 @@ public class VpnTest {
|
|||
|
||||
@Test
|
||||
public void testVpnMeterednessWithNonNullUnderlyingNetwork() throws Exception {
|
||||
if (!supportedHardware()) {
|
||||
return;
|
||||
}
|
||||
Network underlyingNetwork = mCM.getActiveNetwork();
|
||||
if (underlyingNetwork == null) {
|
||||
Log.i(TAG, "testVpnMeterednessWithNonNullUnderlyingNetwork cannot execute"
|
||||
|
|
@ -1609,9 +1584,6 @@ public class VpnTest {
|
|||
|
||||
@Test
|
||||
public void testAlwaysMeteredVpnWithNullUnderlyingNetwork() throws Exception {
|
||||
if (!supportedHardware()) {
|
||||
return;
|
||||
}
|
||||
Network underlyingNetwork = mCM.getActiveNetwork();
|
||||
if (underlyingNetwork == null) {
|
||||
Log.i(TAG, "testAlwaysMeteredVpnWithNullUnderlyingNetwork cannot execute"
|
||||
|
|
@ -1636,9 +1608,6 @@ public class VpnTest {
|
|||
|
||||
@Test
|
||||
public void testAlwaysMeteredVpnWithNonNullUnderlyingNetwork() throws Exception {
|
||||
if (!supportedHardware()) {
|
||||
return;
|
||||
}
|
||||
Network underlyingNetwork = mCM.getActiveNetwork();
|
||||
if (underlyingNetwork == null) {
|
||||
Log.i(TAG, "testAlwaysMeteredVpnWithNonNullUnderlyingNetwork cannot execute"
|
||||
|
|
@ -1676,9 +1645,6 @@ public class VpnTest {
|
|||
|
||||
@Test
|
||||
public void testB141603906() throws Exception {
|
||||
if (!supportedHardware()) {
|
||||
return;
|
||||
}
|
||||
final InetSocketAddress src = new InetSocketAddress(0);
|
||||
final InetSocketAddress dst = new InetSocketAddress(0);
|
||||
final int NUM_THREADS = 8;
|
||||
|
|
@ -1786,8 +1752,6 @@ public class VpnTest {
|
|||
*/
|
||||
@Test
|
||||
public void testDownloadWithDownloadManagerDisallowed() throws Exception {
|
||||
assumeTrue(supportedHardware());
|
||||
|
||||
// Start a VPN with DownloadManager package in disallowed list.
|
||||
startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"},
|
||||
new String[] {"192.0.2.0/24", "2001:db8::/32"},
|
||||
|
|
@ -1843,7 +1807,6 @@ public class VpnTest {
|
|||
|
||||
@Test @IgnoreUpTo(Build.VERSION_CODES.R)
|
||||
public void testBlockIncomingPackets() throws Exception {
|
||||
assumeTrue(supportedHardware());
|
||||
final Network network = mCM.getActiveNetwork();
|
||||
assertNotNull("Requires a working Internet connection", network);
|
||||
|
||||
|
|
@ -1912,7 +1875,6 @@ public class VpnTest {
|
|||
|
||||
@Test
|
||||
public void testSetVpnDefaultForUids() throws Exception {
|
||||
assumeTrue(supportedHardware());
|
||||
assumeTrue(SdkLevel.isAtLeastU());
|
||||
|
||||
final Network defaultNetwork = mCM.getActiveNetwork();
|
||||
|
|
@ -1958,6 +1920,81 @@ public class VpnTest {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if packets to a VPN interface's IP arriving on a non-VPN interface are dropped or not.
|
||||
* If the test interface has a different address from the VPN interface, packets must be dropped
|
||||
* If the test interface has the same address as the VPN interface, packets must not be
|
||||
* dropped
|
||||
*
|
||||
* @param duplicatedAddress true to bring up the test interface with the same address as the VPN
|
||||
* interface
|
||||
*/
|
||||
private void doTestDropPacketToVpnAddress(final boolean duplicatedAddress)
|
||||
throws Exception {
|
||||
final NetworkRequest request = new NetworkRequest.Builder()
|
||||
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
|
||||
.removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
|
||||
.addTransportType(TRANSPORT_TEST)
|
||||
.build();
|
||||
final CtsNetUtils.TestNetworkCallback callback = new CtsNetUtils.TestNetworkCallback();
|
||||
mCM.requestNetwork(request, callback);
|
||||
final FileDescriptor srcTunFd = runWithShellPermissionIdentity(() -> {
|
||||
final TestNetworkManager tnm = mTestContext.getSystemService(TestNetworkManager.class);
|
||||
List<LinkAddress> linkAddresses = duplicatedAddress
|
||||
? List.of(new LinkAddress("192.0.2.2/24"),
|
||||
new LinkAddress("2001:db8:1:2::ffe/64")) :
|
||||
List.of(new LinkAddress("198.51.100.2/24"),
|
||||
new LinkAddress("2001:db8:3:4::ffe/64"));
|
||||
final TestNetworkInterface iface = tnm.createTunInterface(linkAddresses);
|
||||
tnm.setupTestNetwork(iface.getInterfaceName(), new Binder());
|
||||
return iface.getFileDescriptor().getFileDescriptor();
|
||||
}, MANAGE_TEST_NETWORKS);
|
||||
final Network testNetwork = callback.waitForAvailable();
|
||||
assertNotNull(testNetwork);
|
||||
final DatagramSocket dstSock = new DatagramSocket();
|
||||
|
||||
testAndCleanup(() -> {
|
||||
startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"} /* addresses */,
|
||||
new String[]{"0.0.0.0/0", "::/0"} /* routes */,
|
||||
"" /* allowedApplications */, "" /* disallowedApplications */,
|
||||
null /* proxyInfo */, null /* underlyingNetworks */,
|
||||
false /* isAlwaysMetered */);
|
||||
|
||||
final FileDescriptor dstUdpFd = dstSock.getFileDescriptor$();
|
||||
checkBlockUdp(srcTunFd, dstUdpFd,
|
||||
InetAddresses.parseNumericAddress("192.0.2.2") /* dstAddress */,
|
||||
InetAddresses.parseNumericAddress("192.0.2.1") /* srcAddress */,
|
||||
duplicatedAddress ? EXPECT_PASS : EXPECT_BLOCK);
|
||||
checkBlockUdp(srcTunFd, dstUdpFd,
|
||||
InetAddresses.parseNumericAddress("2001:db8:1:2::ffe") /* dstAddress */,
|
||||
InetAddresses.parseNumericAddress("2001:db8:1:2::ffa") /* srcAddress */,
|
||||
duplicatedAddress ? EXPECT_PASS : EXPECT_BLOCK);
|
||||
|
||||
// Traffic on VPN should not be affected
|
||||
checkTrafficOnVpn();
|
||||
}, /* cleanup */ () -> {
|
||||
Os.close(srcTunFd);
|
||||
dstSock.close();
|
||||
}, /* cleanup */ () -> {
|
||||
runWithShellPermissionIdentity(() -> {
|
||||
mTestContext.getSystemService(TestNetworkManager.class)
|
||||
.teardownTestNetwork(testNetwork);
|
||||
}, MANAGE_TEST_NETWORKS);
|
||||
}, /* cleanup */ () -> {
|
||||
mCM.unregisterNetworkCallback(callback);
|
||||
});
|
||||
}
|
||||
|
||||
@Test @IgnoreUpTo(Build.VERSION_CODES.S_V2)
|
||||
public void testDropPacketToVpnAddress_WithoutDuplicatedAddress() throws Exception {
|
||||
doTestDropPacketToVpnAddress(false /* duplicatedAddress */);
|
||||
}
|
||||
|
||||
@Test @IgnoreUpTo(Build.VERSION_CODES.S_V2)
|
||||
public void testDropPacketToVpnAddress_WithDuplicatedAddress() throws Exception {
|
||||
doTestDropPacketToVpnAddress(true /* duplicatedAddress */);
|
||||
}
|
||||
|
||||
private ByteBuffer buildIpv4UdpPacket(final Inet4Address dstAddr, final Inet4Address srcAddr,
|
||||
final short dstPort, final short srcPort, final byte[] payload) throws IOException {
|
||||
|
||||
|
|
@ -2001,7 +2038,8 @@ public class VpnTest {
|
|||
private void checkBlockUdp(
|
||||
final FileDescriptor srcTunFd,
|
||||
final FileDescriptor dstUdpFd,
|
||||
final boolean ipv6,
|
||||
final InetAddress dstAddress,
|
||||
final InetAddress srcAddress,
|
||||
final boolean expectBlock) throws Exception {
|
||||
final Random random = new Random();
|
||||
final byte[] sendData = new byte[100];
|
||||
|
|
@ -2009,15 +2047,15 @@ public class VpnTest {
|
|||
final short dstPort = (short) ((InetSocketAddress) Os.getsockname(dstUdpFd)).getPort();
|
||||
|
||||
ByteBuffer buf;
|
||||
if (ipv6) {
|
||||
if (dstAddress instanceof Inet6Address) {
|
||||
buf = buildIpv6UdpPacket(
|
||||
(Inet6Address) TEST_IP6_DST_ADDR.getAddress(),
|
||||
(Inet6Address) TEST_IP6_SRC_ADDR.getAddress(),
|
||||
(Inet6Address) dstAddress,
|
||||
(Inet6Address) srcAddress,
|
||||
dstPort, TEST_SRC_PORT, sendData);
|
||||
} else {
|
||||
buf = buildIpv4UdpPacket(
|
||||
(Inet4Address) TEST_IP4_DST_ADDR.getAddress(),
|
||||
(Inet4Address) TEST_IP4_SRC_ADDR.getAddress(),
|
||||
(Inet4Address) dstAddress,
|
||||
(Inet4Address) srcAddress,
|
||||
dstPort, TEST_SRC_PORT, sendData);
|
||||
}
|
||||
|
||||
|
|
@ -2043,8 +2081,10 @@ public class VpnTest {
|
|||
final FileDescriptor srcTunFd,
|
||||
final FileDescriptor dstUdpFd,
|
||||
final boolean expectBlock) throws Exception {
|
||||
checkBlockUdp(srcTunFd, dstUdpFd, false /* ipv6 */, expectBlock);
|
||||
checkBlockUdp(srcTunFd, dstUdpFd, true /* ipv6 */, expectBlock);
|
||||
checkBlockUdp(srcTunFd, dstUdpFd, TEST_IP4_DST_ADDR.getAddress(),
|
||||
TEST_IP4_SRC_ADDR.getAddress(), expectBlock);
|
||||
checkBlockUdp(srcTunFd, dstUdpFd, TEST_IP6_DST_ADDR.getAddress(),
|
||||
TEST_IP6_SRC_ADDR.getAddress(), expectBlock);
|
||||
}
|
||||
|
||||
private class DetailedBlockedStatusCallback extends TestableNetworkCallback {
|
||||
|
|
|
|||
|
|
@ -171,4 +171,16 @@ public class HostsideVpnTests extends HostsideNetworkTestCase {
|
|||
public void testSetVpnDefaultForUids() throws Exception {
|
||||
runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testSetVpnDefaultForUids");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDropPacketToVpnAddress_WithoutDuplicatedAddress() throws Exception {
|
||||
runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest",
|
||||
"testDropPacketToVpnAddress_WithoutDuplicatedAddress");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDropPacketToVpnAddress_WithDuplicatedAddress() throws Exception {
|
||||
runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest",
|
||||
"testDropPacketToVpnAddress_WithDuplicatedAddress");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue