ICMP sockets



なんてことを書いてますが、同僚から「Arch Linux でやるとなぜか ping が実行できてしまう」という情報が。確かに Arch でやると実行できてしまいます。

$ lsb_release -d
Description:    Arch Linux
$ cp /usr/bin/ping .
$ getcap ./ping 
$ ./ping -c 1
PING ( 56(84) bytes of data.
64 bytes from icmp_seq=1 ttl=64 time=0.025 ms

--- ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.025/0.025/0.025/0.000 ms

strace とかで見てみるとどうも SOCK_RAW でなく SOCK_DGRAM を使ってる模様。どうやらこれらしい。hayajo さんからも同じ情報を頂いて自信を持って、これを手がかりにググってみると、

icmp(7) にも記載が。えー、2.6.39 から?

$ man icmp
       ping_group_range (two integers; default: see below; since Linux 2.6.39)
              Range of the group IDs (minimum and maximum  group  IDs,  inclu‐
              sive) that are allowed to create ICMP Echo sockets.  The default
              is "1 0", which means no group is allowed to  create  ICMP  Echo

いやー、Linux 奥が深いですね。こんなの知りませんでした。Arch を確認してみると確かに設定されています。

$ sysctl -a 2>/dev/null | grep ping_group_range 
net.ipv4.ping_group_range = 0    2147483647

Plamo だと

$ /sbin/sysctl -a 2>/dev/null | grep ping
net.ipv4.ping_group_range = 1    0

Arch の値はやりすぎ感あるのでとりあえず 0〜65534 とすると、

$ sudo sysctl -w net.ipv4.ping_group_range="0 65534"
net.ipv4.ping_group_range = 0 65534
$ /sbin/sysctl -n net.ipv4.ping_group_range
0  65534


$ cp /bin/ping .
$ /sbin/getcap ./ping 
$ ./ping -c1
PING ( 56(84) バイトのデータ
64 バイト応答 送信元 icmp_seq=1 ttl=64 時間=0.013ミリ秒

--- ping 統計 ---
送信パケット数 1, 受信パケット数 1, パケット損失 0%, 時間 0ミリ秒
rtt 最小/平均/最大/mdev = 0.013/0.013/0.013/0.000ミリ秒


ちなみに「安全のためにコピーしたら外れる」とか書きましたが、cp コマンドでも CAP_SETFCAP ケーパビリティがあれば --preserve=xattr とかやればファイルケーパビリティ保存したままコピーされますね。

(補足・2019-11-29) Twitter で systemd がそのように設定していると教えていただきました。ありがとうございます。

        * This release enables unprivileged programs (i.e. requiring neither
          setuid nor file capabilities) to send ICMP Echo (i.e. ping) requests
          by turning on the "net.ipv4.ping_group_range" sysctl of the Linux
          kernel for the whole UNIX group range, i.e. all processes. This
          change should be reasonably safe, as the kernel support for it was
          specifically implemented to allow safe access to ICMP Echo for
          processes lacking any privileges. If this is not desirable, it can be
          disabled again by setting the parameter to "1 0".