android - 无需 root Android 手机即可监控所有使用网络的应用程序建立的连接的 IP 地址

标签 android networking ip

我正在尝试构建一个 Android 应用程序(无需 root 手机),该应用程序从所有应用程序与手机的网络连接中收集 IP 地址。

我的任务是这个项目,关键是手机必须保持无根状态 - 这(据我所知)意味着我不能使用 tcpdump 或 libpcap,因为这两者似乎都需要手机有根。还有一点,我找到了使用 VPN 服务的解决方案,但是,如果可能的话,我不应该也使用此功能,因为该应用程序应该可以独立运行 - 没有任何“外部”帮助。

我浏览过堆栈溢出和许多其他站点,试图找到一种方法来监视/收集 IP 地址以及我发现的所有解决方案都需要对 Android 手机进行 root 操作。这让我相信这是不可能的,直到我在 Google Play 上找到以下应用程序。

https://play.google.com/store/apps/details?id=com.borgshell.connectiontrackerfree&hl=en

此应用的功能远远超出我的需要,但它以某种方式显示了每个应用正在建立的网络连接的 IP 地址。

总结:

有谁知道从内部应用程序的网络连接中收集 IP 地址的方法

  • 无需root手机

  • 不使用 VPN 服务

谢谢

最佳答案

对于所有对同一问题感到好奇的人,我终于弄清楚了如何完成这项任务,而无需对手机进行 Root 操作或使用 VPN 服务。

解决这个问题的关键,就是在手机上查看以下目录:

/proc/net/(tcp, tcp6, udp, udp6, etc)

另外,这里有一些来自开源项目的代码,基本上可以满足我的需求。

/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net.cts;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.regex.Pattern;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;

public class ListeningPortsTest extends TestCase {

/** Address patterns used to check whether we're checking the right column in /proc/net. */
private static final List<String> ADDRESS_PATTERNS = new ArrayList<String>(2);

static {
    ADDRESS_PATTERNS.add("[0-9A-F]{8}:[0-9A-F]{4}");
    ADDRESS_PATTERNS.add("[0-9A-F]{32}:[0-9A-F]{4}");
}

/** Ports that are allowed to be listening on the emulator. */
private static final List<String> EXCEPTION_PATTERNS = new ArrayList<String>(6);

static {
    // IPv4 exceptions
    EXCEPTION_PATTERNS.add("00000000:15B3"); // 0.0.0.0:5555   - emulator port
    EXCEPTION_PATTERNS.add("0F02000A:15B3"); // 10.0.2.15:5555 - net forwarding for emulator
    EXCEPTION_PATTERNS.add("[0-9A-F]{6}7F:[0-9A-F]{4}"); // IPv4 Loopback

    // IPv6 exceptions
    EXCEPTION_PATTERNS.add("[0]{31}1:[0-9A-F]{4}"); // IPv6 Loopback
    EXCEPTION_PATTERNS.add("[0]{16}[0]{4}[0]{4}[0-9A-F]{6}7F:[0-9A-F]{4}"); // IPv4-6 Conversion
    EXCEPTION_PATTERNS.add("[0]{16}[F]{4}[0]{4}[0-9A-F]{6}7F:[0-9A-F]{4}"); // IPv4-6 Conversion
}

public void testNoListeningTcpPorts() {
    assertNoListeningPorts("/proc/net/tcp", true);
}

public void testNoListeningTcp6Ports() {
    assertNoListeningPorts("/proc/net/tcp6", true);
}

public void testNoListeningUdpPorts() throws Exception {
    assertNoListeningUdpPorts("/proc/net/udp");
}

public void testNoListeningUdp6Ports() throws Exception {
    assertNoListeningUdpPorts("/proc/net/udp6");
}

private static final int RETRIES_MAX = 6;

/**
 * UDP tests can be flaky due to DNS lookups.  Compensate.
 */
private static void assertNoListeningUdpPorts(String procFilePath) throws Exception {
    for (int i = 0; i < RETRIES_MAX; i++) {
        try {
            assertNoListeningPorts(procFilePath, false);
            return;
        } catch (ListeningPortsAssertionError e) {
            if (i == RETRIES_MAX - 1) {
                throw e;
            }
            Thread.sleep(2 * 1000 * i);
        }
    }
    throw new IllegalStateException("unreachable");
}

private static void assertNoListeningPorts(String procFilePath, boolean isTcp) {

    /*
     * Sample output of "cat /proc/net/tcp" on emulator:
     *
     * sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  ...
     * 0: 0100007F:13AD 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0   ...
     * 1: 00000000:15B3 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0   ...
     * 2: 0F02000A:15B3 0202000A:CE8A 01 00000000:00000000 00:00000000 00000000     0   ...
     *
     */

    File procFile = new File(procFilePath);
    Scanner scanner = null;
    try {
        scanner = new Scanner(procFile);
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine().trim();

            // Skip column headers
            if (line.startsWith("sl")) {
                continue;
            }

            String[] fields = line.split("\\s+");
            final int expectedNumColumns = 12;
            assertTrue(procFilePath + " should have at least " + expectedNumColumns
                    + " columns of output " + fields, fields.length >= expectedNumColumns);

            String localAddress = fields[1];
            String state = fields[3];

            assertTrue(procFilePath + " should have an IP address in the second column",
                    isAddress(localAddress));

            if (!isException(localAddress) && isPortListening(state, isTcp)) {
                throw new ListeningPortsAssertionError(
                        "Found port listening on " + localAddress + " in " + procFilePath);
            }
        }
    } catch (FileNotFoundException notFound) {
        fail("Could not open file " + procFilePath + " to check for listening ports.");
    } finally {
        if (scanner != null) {
            scanner.close();
        }
    }
}

private static boolean isAddress(String localAddress) {
    return isPatternMatch(ADDRESS_PATTERNS, localAddress);
}

private static boolean isException(String localAddress) {
    return isPatternMatch(EXCEPTION_PATTERNS, localAddress);
}

private static boolean isPatternMatch(List<String> patterns, String input) {
    for (String pattern : patterns) {
        if (Pattern.matches(pattern, input)) {
            return true;
        }
    }
    return false;
}

private static boolean isPortListening(String state, boolean isTcp) {
    // 0A = TCP_LISTEN from include/net/tcp_states.h
    String listeningState = isTcp ? "0A" : "07";
    return listeningState.equals(state);
}

private static class ListeningPortsAssertionError extends AssertionFailedError {
    private ListeningPortsAssertionError(String msg) {
        super(msg);
    }
  }
}

关于android - 无需 root Android 手机即可监控所有使用网络的应用程序建立的连接的 IP 地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18731656/

相关文章:

sockets - 发送到127.0.0.1的数据包是否充分使用了工作连接套接字?

android - 而是找到了 '1.8'。 Android 需要编译器合规级别 5.0 或 6.0。请使用 Android 工具 > 修复项目属性

android - 手动返回上一个 Activity

java - 如何将文件从一个安卓模拟器传输到我的安卓设备?

docker - NGINX 和 Docker-Compose : host not found in upstream

c++ - ns2的c++代码中的节点在哪里处理数据包?

android - Gson fromJson() 返回具有空属性的对象

java - 应用程序的大小,如何确定

c++ - 如何使用 winsock (c++) 发送\接收非字符数据?

ssl - tomcat 7 ssl 配置 : can multiple certificates be created for an ip address?