V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
ysy950803
V2EX  ›  Linux

traceroute 相关,原始套接字不能直接在 Android 应用层创建吗?

  •  
  •   ysy950803 · 2023-04-08 19:13:25 +08:00 · 1642 次点击
    这是一个创建于 620 天前的主题,其中的信息可能已经有所发展或是发生改变。

    事情是这样的,我需要在 App 里面集成 traceroute ,不是直接执行脚本命令那种(因为没有 ROOT 权限),而是通过 NDK 直接编译成依赖模块。

    于是找到 traceroute 源码,没想到 2023 年还在更新呢,下载下来自己写一下 CMakeList 或者 mk 文件是可以编译并运行在 App 中的。

    GitHub 上也有一些现成的项目(traceroute-for-android),基本都能跑。traceroute 默认用 UDP 发数据包,加 -T(参数说明原文:Use TCP SYN for tracerouting )可以切换成用 TCP 发包,但是一旦加这个参数就会出错。

    在 Linux 系统(比如 Ubuntu )上直接执行 traceroute -T baidu.com 这种命令是不会有问题的,但是编译集成到 Android App 里面,就没法执行带 T 参数的。调试发现,切换成 TCP 发包后,会调用 socket 函数创建原始套接字并且失败,报错提示没有权限,下面是 traceroute 源码:

    static int tcp_init (const sockaddr_any *dest,
    			    unsigned int port_seq, size_t *packet_len_p) {
    	// ...省略
    
    	/*  Create raw socket for tcp   */
    
    	raw_sk = socket (af, SOCK_RAW, IPPROTO_TCP); // SOCK_RAW 表示原始套接字,区别于 SOCK_STREAM ,SOCK_DGRAM 之类的
    	if (raw_sk < 0)
    		error_or_perm ("socket"); // 会创建失败,走到这里,导致整个 traceroute 无法执行
    
    void error_or_perm (const char *str) {
    
    	if (errno == EPERM)
    		fprintf (stderr, "You do not have enough privileges to use "
    				"this traceroute method.");
    	error (str);
    }
    

    UDP 模式没报错,我看源码就是 SOCK_DGRAM 这种方式创建的套接字:

    static void udp_send_probe (probe *pb, int ttl) {
    	int sk;
    	int af = dest_addr.sa.sa_family;
    
    	sk = socket (af, SOCK_DGRAM, protocol);
    

    所以说我是没有办法在应用层(即便是 JNI 这层)去创建原始套接字吗?为什么呢?原始套接字和其他类型的 socket 有啥区别?

    8 条回复    2023-04-12 15:58:51 +08:00
    0o0O0o0O0o
        1
    0o0O0o0O0o  
       2023-04-08 19:24:23 +08:00
    cap_net_raw
    RikkaW
        2
    RikkaW  
       2023-04-08 19:26:32 +08:00
    印象里 SELiunx 不允许,可以看一下 avc: 的 log (
    ysy950803
        3
    ysy950803  
    OP
       2023-04-08 20:42:44 +08:00
    求 Linux 网络编程大佬解惑呀!
    tomychen
        4
    tomychen  
       2023-04-10 15:25:13 +08:00
    创建 raw socket 的前置条件就是 root

    允许非 root 的创建 raw socket 的方法就是用 root 用户给这个进程+s 位
    julyclyde
        5
    julyclyde  
       2023-04-10 16:20:59 +08:00
    为什么 tcp 还需要 raw 呢
    ysy950803
        6
    ysy950803  
    OP
       2023-04-10 23:43:28 +08:00
    @tomychen 谢谢,后来查了下资料确实是,原始套接字比较危险,不开放给非 ROOT 权限的用户。
    qbqbqbqb
        7
    qbqbqbqb  
       2023-04-12 15:57:14 +08:00   ❤️ 1
    @julyclyde 因为 traceroute 的-T 模式是只发一个 SYN ,不是正常的 connect
    qbqbqbqb
        8
    qbqbqbqb  
       2023-04-12 15:58:51 +08:00
    @ysy950803 raw socket 的接收 /发送就约等于抓包 /数据包注入了,所以肯定要 root 。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1008 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 20:13 · PVG 04:13 · LAX 12:13 · JFK 15:13
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.