Bug 39 - Spliced TCP connections will present incorrect peer port to listeners in pasta
Summary: Spliced TCP connections will present incorrect peer port to listeners in pasta
Status: RESOLVED INVALID
Alias: None
Product: passt
Classification: Unclassified
Component: TCP (show other bugs)
Version: unspecified
Hardware: All Linux
: Normal minor
Assignee: nobody
URL:
Depends on:
Blocks:
 
Reported: 2022-11-17 05:00 UTC by David Gibson
Modified: 2023-11-13 04:50 UTC (History)
0 users

See Also:


Attachments

Description David Gibson 2022-11-17 05:00:04 UTC
A server listening on TCP can obtain the socket address of its peer - both the address and the port - either from accept() or with getpeername().  For example with the attached foo.sh script, we can do this:

## Server side

$ socat -u TCP4-LISTEN:9999 EXEC:/home/dwg/src/passt/foo.sh
Peer address: 192.168.17.36
Peer port: 43424
Data:
hello

## Client side

$ echo hello | strace -e getsockname socat -u STDIN TCP4:192.168.17.36:9999
getsockname(5, {sa_family=AF_INET, sin_port=htons(43424), sin_addr=inet_addr("192.168.17.36")}, [112 => 16]) = 0
+++ exited with 0 +++

Note that the source address and port reported by the client with getsockname() is the same as the peer address and port reported on the server.

If the server is running under pasta, the address is translated to the gateway address as expected, but the port number is still preserved:

## Server
$ ./pasta -t 9999 --config-net
# socat -u TCP4-LISTEN:9999 EXEC:/home/dwg/src/passt/foo.sh
Peer address: 192.168.17.1
Peer port: 55922
Data:
hello

## Client
$ echo hello | strace -e getsockname socat -u STDIN TCP4:192.168.17.36:9999
getsockname(5, {sa_family=AF_INET, sin_port=htons(55922), sin_addr=inet_addr("192.168.17.36")}, [112 => 16]) = 0
+++ exited with 0 +++



However, if localhost is used instead of a "real" IP address, the port number is no longer preserved:

## Server
$ ./pasta -t 9999 --config-net
# socat -u TCP4-LISTEN:9999 EXEC:/home/dwg/src/passt/foo.sh
Peer address: 127.0.0.1
Peer port: 41874
Data:
hello

## Client
$ echo hello | strace -e getsockname socat -u STDIN TCP4:localhost:9999
getsockname(5, {sa_family=AF_NETLINK, nl_pid=3885151, nl_groups=00000000}, [12]) = 0
getsockname(5, {sa_family=AF_INET, sin_port=htons(38718), sin_addr=inet_addr("127.0.0.1")}, [28 => 16]) = 0
getsockname(5, {sa_family=AF_INET, sin_port=htons(41860), sin_addr=inet_addr("127.0.0.1")}, [112 => 16]) = 0
+++ exited with 0 +++


This is because coming from localhost uses a spliced socket which has its own source port address different from the originating socket.
Comment 1 David Gibson 2023-11-13 04:50:55 UTC
On consideration, preserving the peer port number really isn't supported by the NAT model we have in mind.  Rather it's merely a coincidence that the "tap" case does preserve the number (for now).

Closing.

Note You need to log in before you can comment on or make changes to this bug.