1
0
mirror of https://passt.top/passt synced 2024-12-22 05:35:23 +00:00

conf, fwd: Make ephemeral port logic more flexible

"Ephemeral" ports are those which the kernel may allocate as local
port numbers for outgoing connections or datagrams.  Because of that,
they're generally not good choices for listening servers to bind to.

Thefore when using -t all, -u all or exclude-only ranges, we map only
non-ephemeral ports.  Our logic for this is a bit rigid though: we
assume the ephemeral ports are always a fixed range at the top of the
port number space.  We also assume PORT_EPHEMERAL_MIN is a multiple of
8, or we won't set the forward bitmap correctly.

Make the logic in conf.c more flexible, using a helper moved into
fwd.[ch], although we don't change which ports we consider ephemeral
(yet).

The new handling is undoubtedly more computationally expensive, but
since it's a once-off operation at start off, I don't think it really
matters.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Laurent Vivier <lvivier@redhat.com>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
David Gibson 2024-08-29 19:58:45 +10:00 committed by Stefano Brivio
parent 712ca32353
commit 1daf6f4615
4 changed files with 27 additions and 7 deletions

12
conf.c
View File

@ -156,9 +156,12 @@ static void conf_ports(const struct ctx *c, char optname, const char *optarg,
die("'all' port forwarding is only allowed for passt");
fwd->mode = FWD_ALL;
memset(fwd->map, 0xff, PORT_EPHEMERAL_MIN / 8);
for (i = 0; i < PORT_EPHEMERAL_MIN; i++) {
for (i = 0; i < NUM_PORTS; i++) {
if (fwd_port_is_ephemeral(i))
continue;
bitmap_set(fwd->map, i);
if (optname == 't') {
ret = tcp_sock_init(c, AF_UNSPEC, NULL, NULL,
i);
@ -259,8 +262,9 @@ static void conf_ports(const struct ctx *c, char optname, const char *optarg,
} while ((p = next_chunk(p, ',')));
if (exclude_only) {
for (i = 0; i < PORT_EPHEMERAL_MIN; i++) {
if (bitmap_isset(exclude, i))
for (i = 0; i < NUM_PORTS; i++) {
if (fwd_port_is_ephemeral(i) ||
bitmap_isset(exclude, i))
continue;
bitmap_set(fwd->map, i);

17
fwd.c
View File

@ -27,6 +27,23 @@
#include "lineread.h"
#include "flow_table.h"
/* Empheral port range: values from RFC 6335 */
static const in_port_t fwd_ephemeral_min = (1 << 15) + (1 << 14);
static const in_port_t fwd_ephemeral_max = NUM_PORTS - 1;
/**
* fwd_port_is_ephemeral() - Is port number ephemeral?
* @port: Port number
*
* Return: true if @port is ephemeral, that is may be allocated by the kernel as
* a local port for outgoing connections or datagrams, but should not be
* used for binding services to.
*/
bool fwd_port_is_ephemeral(in_port_t port)
{
return (port >= fwd_ephemeral_min) && (port <= fwd_ephemeral_max);
}
/* See enum in kernel's include/net/tcp_states.h */
#define UDP_LISTEN 0x07
#define TCP_LISTEN 0x0a

2
fwd.h
View File

@ -12,6 +12,8 @@ struct flowside;
/* Number of ports for both TCP and UDP */
#define NUM_PORTS (1U << 16)
bool fwd_port_is_ephemeral(in_port_t port);
enum fwd_ports_mode {
FWD_UNSET = 0,
FWD_SPEC = 1,

3
util.h
View File

@ -95,9 +95,6 @@
#define FD_PROTO(x, proto) \
(IN_INTERVAL(c->proto.fd_min, c->proto.fd_max, (x)))
#define PORT_EPHEMERAL_MIN ((1 << 15) + (1 << 14)) /* RFC 6335 */
#define PORT_IS_EPHEMERAL(port) ((port) >= PORT_EPHEMERAL_MIN)
#define MAC_ZERO ((uint8_t [ETH_ALEN]){ 0 })
#define MAC_IS_ZERO(addr) (!memcmp((addr), MAC_ZERO, ETH_ALEN))