Why ping uses UDP port 1025
2021-02-20 01:44:33 Author: terenceli.github.io(查看原文) 阅读量:172 收藏

2021-02-19

Recently I noticed that the ping source code has an interesting trick. It creates a UDP socket and bind connect to the destnation using port 1025. The code is here.

At first glance it is strange as we know the ping just uses ICMP to detect the connection of two ip.

So Let’s see what happened.

In one terminal we use tcpdump to capture the packet.

    root@ubuntu:/home/test# tcpdump -nn -vv host 8.8.8.8

In another terminal we strace the ping.

    test@ubuntu:~$ strace -o ping.txt ping 8.8.8.8 -c 1

After the ping terminated. We can see the tcmpdump has no packet related with the 1025 port.

    root@ubuntu:/home/test# tcpdump -nn -vv host 8.8.8.8
    tcpdump: listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
    07:29:19.390097 IP (tos 0x0, ttl 64, id 9390, offset 0, flags [DF], proto ICMP (1), length 84)
        192.168.80.146 > 8.8.8.8: ICMP echo request, id 2, seq 1, length 64
    07:29:19.688639 IP (tos 0x0, ttl 128, id 44019, offset 0, flags [none], proto ICMP (1), length 84)
        8.8.8.8 > 192.168.80.146: ICMP echo reply, id 2, seq 1, length 64

Let’s see the strace log.

    socket(AF_INET, SOCK_DGRAM, IPPROTO_IP) = 5
    connect(5, {sa_family=AF_INET, sin_port=htons(1025), sin_addr=inet_addr("8.8.8.8")}, 16) = 0
    getsockname(5, {sa_family=AF_INET, sin_port=htons(43043), sin_addr=inet_addr("192.168.80.146")}, [16]) = 0
    close(5)                                = 0

The UDP 1025 port is just there and exists just socket/connect/getsockname/close.

So after search the internet I just found the is a trick to get current source IP that ping program used.

The use of 1025 is in the condition of no source ip specified. If we specify the source IP, there is no connect in the strace log.

    test@ubuntu:~$ strace -o ping.txt ping -I 192.168.80.146  8.8.8.8 -c 1

Finally let’s just go to kernel to see.

    SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
            int, addrlen)
    {
        return __sys_connect(fd, uservaddr, addrlen);
    }

    __sys_connect
        ->__sys_connect_file
            ->sock->ops->connect(inet_stream_connect)
                ->__inet_stream_connect
                    ->sk->sk_prot->connect(ip4_datagram_connect)
                        ->__ip4_datagram_connect
                            ->ip_route_connect
                                ->ip_route_connect_init
                                ->__ip_route_output_key
                                    ->ip_route_output_key_hash
                                        ->ip_route_output_key_hash_rcu
                                ->flowi4_update_output
                                ->ip_route_output_flow

It seems that ‘ip_route_output_key_hash_rcu’ choose the source address.

    ip_route_output_key_hash_rcu
	if (!fl4->saddr) {
		if (ipv4_is_multicast(fl4->daddr))
			fl4->saddr = inet_select_addr(dev_out, 0,
						      fl4->flowi4_scope);
		else if (!fl4->daddr)
			fl4->saddr = inet_select_addr(dev_out, 0,
						      RT_SCOPE_HOST);
	}


    __ip4_datagram_connect
    if (!inet->inet_saddr)
        inet->inet_saddr = fl4->saddr;	/* Update source address */

In the getsockname syscall, we can see. It get the source IP from ‘inet->inet_saddr’.

    int inet_getname(struct socket *sock, struct sockaddr *uaddr,
            int peer)
    {
        struct sock *sk		= sock->sk;
        struct inet_sock *inet	= inet_sk(sk);
        DECLARE_SOCKADDR(struct sockaddr_in *, sin, uaddr);

        sin->sin_family = AF_INET;
        if (peer) {
            ...
        } else {
            __be32 addr = inet->inet_rcv_saddr;
            if (!addr)
                addr = inet->inet_saddr;
            sin->sin_port = inet->inet_sport;
            sin->sin_addr.s_addr = addr;
        }
        ...
    }
    EXPORT_SYMBOL(inet_getname);

Reference

It can be found in following websites:

https://echorand.me/posts/my-own-ping/

https://jeffpar.github.io/kbarchive/kb/129/Q129065/

https://github.com/iputils/iputils/issues/125

https://stackoverflow.com/questions/25879280/getting-my-own-ip-address-by-connecting-using-udp-socket



blog comments powered by


文章来源: http://terenceli.github.io/%E6%8A%80%E6%9C%AF/2021/02/19/ping-1025
如有侵权请联系:admin#unsafe.sh