go-ping / ping

ICMP Ping library for Go
MIT License
1.33k stars 345 forks source link

Non-privileged scenarios do not work #180

Closed HuKeping closed 1 year ago

HuKeping commented 3 years ago

After commit 62f79f1f4f36fc821eebb131548270d4d8b68653 upstream, the go-ping program blocks the received ICMP packets because the received ICMP identifier is different from the senter's echo identifier

We think it may caused by the Linux kernel automatically assigns an identifier as the local receive port number in non-privileged cases.

HuKeping commented 3 years ago

PTAL @mem

CHTJonas commented 3 years ago

I'm not experiencing this issue.

chtj2@pip:/tmp/chtj2$ uname -a
Linux pip 5.4.0-74-generic #83-Ubuntu SMP Sat May 8 02:35:39 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

chtj2@pip:/tmp/chtj2$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.3 LTS
Release:        20.04
Codename:       focal

chtj2@pip:/tmp/chtj2$ go version
go version go1.15.2 linux/amd64

chtj2@pip:/tmp/chtj2$ git clone https://github.com/go-ping/ping.git
Cloning into 'ping'...
remote: Enumerating objects: 290, done.
remote: Counting objects: 100% (23/23), done.
remote: Compressing objects: 100% (17/17), done.
remote: Total 290 (delta 8), reused 12 (delta 4), pack-reused 267
Receiving objects: 100% (290/290), 1.28 MiB | 2.00 MiB/s, done.
Resolving deltas: 100% (144/144), done.

chtj2@pip:/tmp/chtj2$ cd ping/

chtj2@pip:/tmp/chtj2/ping$ go run cmd/ping/ping.go google.com
go: downloading golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4
go: downloading golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
go: downloading github.com/google/uuid v1.2.0
go: downloading golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005
PING google.com (142.250.187.238):
32 bytes from 142.250.187.238: icmp_seq=0 time=6.165858ms ttl=116
32 bytes from 142.250.187.238: icmp_seq=1 time=6.051684ms ttl=116
32 bytes from 142.250.187.238: icmp_seq=2 time=6.041586ms ttl=116
32 bytes from 142.250.187.238: icmp_seq=3 time=6.016118ms ttl=116
32 bytes from 142.250.187.238: icmp_seq=4 time=6.064066ms ttl=116
32 bytes from 142.250.187.238: icmp_seq=5 time=5.871934ms ttl=116
32 bytes from 142.250.187.238: icmp_seq=6 time=5.958188ms ttl=116
32 bytes from 142.250.187.238: icmp_seq=7 time=6.023026ms ttl=116
^C
--- google.com ping statistics ---
8 packets transmitted, 8 packets received, 0 duplicates, 0% packet loss
round-trip min/avg/max/stddev = 5.871934ms/6.024059ms/6.165858ms/79.312µs

@HuKeping, please could you elaborate on what Linux distribution and kernel version you are running?

Do you have some kernel code that you link to or something else that supports your hypothesis that Linux is assigning the receive port number as the identifier?

RabeaWahab commented 3 years ago

I am having this issue, running the same commands as @CHTJonas , on Macbook AIR M1 - Darwin Kernel Version 20.6.0: Wed Jun 23 00:26:27 PDT 2021; root:xnu-7195.141.2~5/RELEASE_ARM64_T8101 arm64


➜  services git clone https://github.com/go-ping/ping.git
Cloning into 'ping'...
remote: Enumerating objects: 290, done.
remote: Counting objects: 100% (23/23), done.
remote: Compressing objects: 100% (17/17), done.
remote: Total 290 (delta 8), reused 12 (delta 4), pack-reused 267
Receiving objects: 100% (290/290), 1.28 MiB | 2.58 MiB/s, done.
Resolving deltas: 100% (144/144), done.

➜  services cd ping

➜  ping git:(master) go run cmd/ping/ping.go google.com
go: downloading golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4
go: downloading golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005
PING google.com (172.253.124.100): ------> left it running for about 30 seconds
^C
--- google.com ping statistics ---
121 packets transmitted, 0 packets received, 0 duplicates, 100% packet loss
round-trip min/avg/max/stddev = 0s/0s/0s/0s
fkr commented 3 years ago

@RabeaWahab while on macOS no proper error is thrown on (other) BSDs (such as OpenBSD and FreeBSD) proper errors are given, raw sockets are only for use by superusers. I actually ran into this couple weeks ago and still wanted to track down why no hard error is thrown on macOS.

CHTJonas commented 3 years ago

@RabeaWahab again, I am not experiencing this either on Darwin Kernel Version 20.6.0: Mon Aug 30 06:12:21 PDT 2021; root:xnu-7195.141.6~3/RELEASE_X86_64 x86_64 i386:

$ git clone https://github.com/go-ping/ping.git
Cloning into 'ping'...
remote: Enumerating objects: 290, done.
remote: Counting objects: 100% (23/23), done.
remote: Compressing objects: 100% (17/17), done.
remote: Total 290 (delta 8), reused 12 (delta 4), pack-reused 267
Receiving objects: 100% (290/290), 1.28 MiB | 8.37 MiB/s, done.
Resolving deltas: 100% (144/144), done.

$ cd ping

$ go run cmd/ping/ping.go google.com
PING google.com (172.217.169.46):
32 bytes from 172.217.169.46: icmp_seq=0 time=6.768ms ttl=119
32 bytes from 172.217.169.46: icmp_seq=1 time=6.536ms ttl=119
32 bytes from 172.217.169.46: icmp_seq=2 time=6.559ms ttl=119
32 bytes from 172.217.169.46: icmp_seq=3 time=7.089ms ttl=119
32 bytes from 172.217.169.46: icmp_seq=4 time=7.562ms ttl=119
32 bytes from 172.217.169.46: icmp_seq=5 time=6.97ms ttl=119
32 bytes from 172.217.169.46: icmp_seq=6 time=7.372ms ttl=119
32 bytes from 172.217.169.46: icmp_seq=7 time=6.634ms ttl=119
^C
--- google.com ping statistics ---
8 packets transmitted, 8 packets received, 0 duplicates, 0% packet loss
round-trip min/avg/max/stddev = 6.536ms/6.93625ms/7.562ms/358.485µs

I'm trying to work out why this is only an issue for certain folks. FWIW the official documentation suggests that non-privileged datagram-oriented (UDP-based) ping only works on Linux and macOS so that would explain errors on other operating systems, but not why it's broken for some using those two OS'es.

mem commented 3 years ago

I'm clueless when it comes to Darwin... on Linux, there's something that you have to configure it to make rootless ping work (the group range that is allowed to send ICMP packets without privileges).

Is there something similar for Darwin, or is there something similar that is specific to MacOS? This suggests it's enabled by default as long as you use SOCK_DGRAM (UDP/IP), which this code does.

fkr commented 3 years ago

Snooping the traffic on the corresponding network interface, I see packets leaving and returning the machine, so I suspect the issue is somewhere within the data path of the processing of the return packets. I'm seeing this on BigSur as well as the latest Monterey beta. Will dig into the code in the next days.

CHTJonas commented 3 years ago

@fkr are you running any firewall/AV software on your macOS machine or is it relatively stock?

fkr commented 3 years ago

@CHTJonas thanks for your explicit question, since that actually did remind me of something that I should have initially thought about. I indeed have 'Little Snitch' installed. I actually turned it off for testing and since I actually saw the packets leaving my machine (as well as returning), I'd thought it is fully disabled. However - turns out - as long as the associated System Extension is loaded: the example program does not work. The moment 'Little Snitch' is gone, the example program works.

Imho the darwin / macOS case can be closed. I still want to track done in which way the behaviour is changed, but this is not the scope of this issue ;)

Sorry for the noise.

CHTJonas commented 3 years ago

Good to hear we've narrowed down the source! I had a moment yesterday when I recalled that someone else had reported issues and traced them down to some piece of security software...

If this works with the system extension unloaded but not with it loaded then to me that feels like a bug in Little Snitch. I wonder if LS is replacing/randomising the part of the header in the UDP packet that we use for tracking?

Anyway, this is resolved on macOS/OSX from our side as far as I can see, leaving only the issue experienced by @HuKeping on Linux. There are probably some other outstanding tasks from this thread such as: