[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20200221203522.25716-1-kuniyu@amazon.co.jp>
Date: Sat, 22 Feb 2020 05:35:22 +0900
From: Kuniyuki Iwashima <kuniyu@...zon.co.jp>
To: <edumazet@...gle.com>
CC: <davem@...emloft.net>, <kuni1840@...il.com>, <kuniyu@...zon.co.jp>,
<kuznet@....inr.ac.ru>, <netdev@...r.kernel.org>,
<osa-contribution-log@...zon.com>, <yoshfuji@...ux-ipv6.org>
Subject: Re: [PATCH net-next 0/3] ImpArove bind(addr, 0) behaviour.
From: Eric Dumazet <edumazet@...gle.com>
Date: Thu, 20 Feb 2020 11:58:00 -0800
> On Thu, Feb 20, 2020 at 7:20 AM Kuniyuki Iwashima <kuniyu@...zon.co.jp> wrote:
> >
> > Currently we fail to bind sockets to ephemeral ports when all of the ports
> > are exhausted even if all sockets have SO_REUSEADDR enabled. In this case,
> > we still have a chance to connect to the different remote hosts.
> >
> > The second and third patches fix the behaviour to fully utilize all space
> > of the local (addr, port) tuples.
> >
> > Kuniyuki Iwashima (3):
> > tcp: Remove unnecessary conditions in inet_csk_bind_conflict().
> > tcp: bind(addr, 0) remove the SO_REUSEADDR restriction when ephemeral
> > ports are exhausted.
> > tcp: Prevent port hijacking when ports are exhausted
> >
> > net/ipv4/inet_connection_sock.c | 36 ++++++++++++++++++++++-----------
> > 1 file changed, 24 insertions(+), 12 deletions(-)
>
> I am travelling at the moment, so I can not really look at these
> patches with enough time.
>
> I would appreciate it if you provide tests to demonstrate your patches are safe.
>
> Thanks.
I wrote a program below and run without patches and with patches.
Without patches, we cannot reuse ports in any pattern. With patches, we can
reuse ports if all of the socket have SO_REUSEADDR enabled and the first
socket is not in TCP_LISTEN.
So, I am sorry that the description of my third patch is wrong.
> In this case, we should be able to bind sockets to the same port only if
> the user has the first listening socket on the port
Also, I succeeded to reuse ports if both sockets are in TCP_CLOSE and have
SO_REUSEADDR and SO_REUSEPORT enabled, and I succeeded to call listen for
both sockets. I think only this case is not safe, so let me check the
condition.
Thank you.
=====
#include <arpa/inet.h>
#include <errno.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
char *str[] = {
"both",
"sk1",
"sk2",
"none",
};
#define render_opt(x, i) (x[i] && x[i+1] ? str[0] : \
(x[i] ? str[1] : \
(x[i+1]? str[2] : str[3])))
int main(void) {
struct sockaddr_in local_addr;
char addr[] = "10.0.2.15";
char ip_str[16];
unsigned int port;
int fd[2];
int len = sizeof(local_addr);
int error = 0;
int reuseaddr, reuseport;
int opts[16][4] = { /* SO_REUSEADDR 1,2 SO_REUSEPORT 1,2 */
{0,0,0,0},
{0,0,0,1},
{0,0,1,0},
{0,0,1,1},
{0,1,0,0},
{0,1,0,1},
{0,1,1,0},
{0,1,1,1},
{1,0,0,0},
{1,0,0,1},
{1,0,1,0},
{1,0,1,1},
{1,1,0,0},
{1,1,0,1},
{1,1,1,0},
{1,1,1,1}
};
int listen_opt[4][2] = {
{0,0},
{1,0},
{0,1},
{1,1}
};
printf("SO_REUSEADDR\tSO_REUSEPORT\tLISTEN\tADDR1\t\t\tADDR2\t\t\tRESULT\n");
for (int i = 0; i < 16; i++) {
for (int l = 0; l < 4; l++) {
printf("%s\t\t%s\t\t%s\t",
render_opt(opts[i], 0),
render_opt(opts[i], 2),
render_opt(listen_opt[l], 0));
for (int j = 0; j < 2; j++) {
fd[j] = socket(AF_INET, SOCK_STREAM, 0);
reuseaddr = opts[i][j];
reuseport = opts[i][j + 2];
setsockopt(fd[j], SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(int));
setsockopt(fd[j], SOL_SOCKET, SO_REUSEPORT, &reuseport, sizeof(int));
memset(&local_addr, 0, sizeof(local_addr));
local_addr.sin_family = AF_INET;
local_addr.sin_addr.s_addr = inet_addr(addr);
local_addr.sin_port = 0;
error = bind(fd[j], (struct sockaddr *)&local_addr, len);
memset(&local_addr, 0, sizeof(local_addr));
getsockname(fd[j], (struct sockaddr *)&local_addr, &len);
inet_ntop(AF_INET, &local_addr.sin_addr, ip_str, sizeof(ip_str));
port = ntohs(local_addr.sin_port);
printf("%s:%u\t\t", ip_str, port);
if (error < 0)
goto error;
if (listen_opt[l][j] == 1) {
error = listen(fd[j], 5);
if (error < 0)
goto error;
}
}
printf("o\n");
goto close;
error:
printf("x\t%d: %s\n", errno, strerror(errno));
close:
close(fd[0]);
close(fd[1]);
}
}
return 0;
}
=====
===Without patches===
# sysctl -w net.ipv4.ip_local_port_range="32768 32768"
[ 9.830967] ip_local_port_range: prefer different parity for start/end values.
net.ipv4.ip_local_port_range = 32768 32768
# ./reuse
SO_REUSEADDR SO_REUSEPORT LISTEN ADDR1 ADDR2 RESULT
none none none 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none none sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none none sk2 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none none both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none sk2 none 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none sk2 sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none sk2 sk2 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none sk2 both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none sk1 none 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none sk1 sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none sk1 sk2 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none sk1 both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none both none 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none both sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none both sk2 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none both both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 none none 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 none sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 none sk2 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 none both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 sk2 none 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 sk2 sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 sk2 sk2 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 sk2 both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 sk1 none 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 sk1 sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 sk1 sk2 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 sk1 both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 both none 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 both sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 both sk2 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 both both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 none none 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 none sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 none sk2 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 none both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 sk2 none 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 sk2 sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 sk2 sk2 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 sk2 both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 sk1 none 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 sk1 sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 sk1 sk2 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 sk1 both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 both none 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 both sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 both sk2 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 both both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
both none none 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
both none sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
both none sk2 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
both none both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
both sk2 none 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
both sk2 sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
both sk2 sk2 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
both sk2 both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
both sk1 none 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
both sk1 sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
both sk1 sk2 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
both sk1 both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
both both none 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
both both sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
both both sk2 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
both both both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
=====================
===With patches===
# sysctl -w net.ipv4.ip_local_port_range="32768 32768"
[ 21.732038] ip_local_port_range: prefer different parity for start/end values.
net.ipv4.ip_local_port_range = 32768 32768
# ./reuse
SO_REUSEADDR SO_REUSEPORT LISTEN ADDR1 ADDR2 RESULT
none none none 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none none sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none none sk2 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none none both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none sk2 none 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none sk2 sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none sk2 sk2 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none sk2 both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none sk1 none 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none sk1 sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none sk1 sk2 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none sk1 both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none both none 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none both sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none both sk2 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
none both both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 none none 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 none sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 none sk2 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 none both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 sk2 none 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 sk2 sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 sk2 sk2 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 sk2 both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 sk1 none 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 sk1 sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 sk1 sk2 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 sk1 both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 both none 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 both sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 both sk2 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk2 both both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 none none 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 none sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 none sk2 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 none both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 sk2 none 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 sk2 sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 sk2 sk2 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 sk2 both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 sk1 none 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 sk1 sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 sk1 sk2 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 sk1 both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 both none 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 both sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 both sk2 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
sk1 both both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
both none none 10.0.2.15:32768 10.0.2.15:32768 o
both none sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
both none sk2 10.0.2.15:32768 10.0.2.15:32768 o
both none both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
both sk2 none 10.0.2.15:32768 10.0.2.15:32768 o
both sk2 sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
both sk2 sk2 10.0.2.15:32768 10.0.2.15:32768 o
both sk2 both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
both sk1 none 10.0.2.15:32768 10.0.2.15:32768 o
both sk1 sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
both sk1 sk2 10.0.2.15:32768 10.0.2.15:32768 o
both sk1 both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
both both none 10.0.2.15:32768 10.0.2.15:32768 o
both both sk1 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
both both sk2 10.0.2.15:32768 10.0.2.15:32768 o
both both both 10.0.2.15:32768 0.0.0.0:0 x 98: Address already in use
==================
Powered by blists - more mailing lists