3

不需要 root 权限的 ICMP ping

 3 years ago
source link: https://blog.lilydjwg.me/2013/10/29/non-privileged-icmp-ping.41390.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

不需要 root 权限的 ICMP ping

本文来自依云's Blog,转载请注明。

ICMP 套接字是两年前 Linux 内核新加入的功能,目的是允许不需要 set-user-id 和CAP_NET_RAW权限的 ping 程序的实现。大家都知道,set-user-id 程序经常成为本地提权的途径。在 Linux 内核加入此功能之前,以安全为目标的 Openwall GNU/*/Linux 实现了除 ping 程序之外的所有程序去 suid 化……这个功能也是由他们提出并加入的。

我并没有在 man 手册中看到关于 ICMP 套接字的信息。关于 ICMP 套接字使用的细节来自于内核邮件列表

使用 ICMP 套接字的好处

  1. 程序不需要特殊的权限;
  2. 内核会帮助搞定一些工作。

坏处是:

  1. 基本没有兼容性可讲;
  2. 需要调整一个内核参数。

这个内核参数net.ipv4.ping_group_range,是一对整数,指定了允许使用 ICMP 套接字的组 ID的范围。默认值为1 0,意味着没有人能够使用这个特性。手动修改下:

sudo sysctl -w net.ipv4.ping_group_range='0 10'

当然你可以直接去写/proc/sys/net/ipv4/ping_group_range文件。

如果系统不支持这个特性,在创建套接字的时候会得到「Protocol not supported」错误,而如果没有权限,则会得到「Permission denied」错误。

创建 ICMP 套接字的方法如下:

import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_ICMP)

它的类型和 UDP 套接字一样,是SOCK_DGRAM,不是SOCK_RAW哦。这意味着你不会收到 20 字节的 IP 头。不仅仅如此,使用 ICMP 套接字不需要手工计算校验和,因为内核会重新计算的。ICMP id 也是由内核填的。在接收的时候,内核会只把相应 id 的 ICMP 回应返回给程序,不需要自己或者要求内核过滤了。

所以,要组装一个 ICMP ECHO 请求包头很容易了:

header = struct.pack('bbHHh', 8, 0, 0, 0, seq)

这五项依次是:类型(ECHO_REQUEST)、code(只能为零)、校验和(不需要管)、id(不需要管)、序列号。

接收起来也简单,只要看一下序列号知道是回应自己发的哪个包的就行了。

这里是我的一个很简单的实例。

附注:Mac OS X 在 Linux 之前实现了类似的功能。但是行为可能不太一样。有报告校验和需要自己计算的,也有报告发送正确但是返回报文是乱码的。另,FreeBSD 和 OpenBSD 不支持这个特性。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK