Forward a range of ports to a container

Hi,

I am trying to forward a range of udp ports of my host to a container.
How can this be done ?

I tried
incus config device add <instance_name> <device_name> proxy listen=::[-][,] connect=:: bind=<host/instance>

but connect side can only target a single port… I’m would like to avoid to create thousands of proxies !!

Is there a dedicated syntax for that ? (or am I totally missing something ??)

Thanks
Franck

You can create network forwards.

They work a bit differently than you are describing but they solve the problem.

2 Likes

Is there a description somewhere of why there are two similar looking solutions, and the cons and benefits of each ?

As I understand it, both solutions would work to forward port 80 to a conainer:

incus network forward port add default xx.yy.zz.ww tcp 80 my.con.ta.ner 80

is equivalent to

incus config device add mycontainer port-80 proxy listen=tcp:0.0.0.0:80 connect=tcp:127.0.0.1:80

Is it ? and which ground would I choose one or the other ?

Good question.

I don’t think I have read something like that.

You can read the intro on this page, though. It gives a few examples that can not be achieved with network forwards.

Ok, besides these general considerations, maybe I should be a bit more specific, in case someone can help on my specific use case…

I have a container hosting a WebRTC server (galene).
It uses the incusbr0 bridge network.
It embeds a TURN server listening on ports tcp 1194 and udp 1194 (so inside the container).
I also need to have the internet clients create WebRTC “tunnels” with Galène on the container (on a udp port range from 18100 to 19100).

What would be the way to achieve this ?
Proxy devices ? With nat=true or not ?
Network forward ?

Up to now on my server, I have mainly set up a proxy device on ports 80 and 443 to a container with Nginx acting as a reverse proxy to web sites. That was easy. WebRTC and TURN are more sensitive beasts for me :slight_smile:

I would start with network forwards. If that does not work for some reason, you could use HAProxy. It is pretty easy to set up.

At least these are my first thoughts. I have not deployed WebRTC before.

You can also do it with proxy device:

For example on a nginx container for ports between 2000 and 2999 you can create a port2XXXproxy (or any other name) device this way:

incus config device add nginx port2XXXproxy proxy listen=tcp:0.0.0.0:2000-2999 connect=tcp:127.0.0.1:2000-2999
1 Like

Does it work ? If so, maybe the doc should be updated, as it says:

incus config device add <instance_name> <device_name> proxy listen=::[-][,] connect=:: bind=<host/instance>

So reading the doc looks like you can redirect a port range, or a list of ports, to one port, but not to a port range.

I’m not sufficiently comfortable with what proxy does, nor with iptables / nftables, to be sure…

Sorry, there’s a typo at the earlier reply that I plus’ed. Here’s a full example.

We want to create an Incus container and redirect 100 ports from the host to 100 consecutive ports in the container. It is redundant to specify the range IN THE CONTAINER, therefore the syntax is to just specify the starting port in the container and Incus will fill up the rest of the ports.

We launch a container named myproxy, then add a proxy device called myrange to forward a range of ports. Then, we install a Web server in the container, and set it up so that it has several virtual hosts/server blocks on ports 80-85 (the myrange enables forwarding for the range of 80-180, 100 ports).

$ incus launch images:debian/12/cloud myproxy
Launching myproxy
$ incus config device add myproxy myrange proxy listen=tcp:0.0.0.0:14000-14100 connect=tcp:127.0.0.1:80
Device myrange added to myproxy
$ incus exec myproxy -- apt install -y nginx
...
Setting up nginx (1.22.1-9) ...
$ incus exec myproxy -- vi /etc/nginx/sites-enabled/default
$ incus exec myproxy -- cat /etc/nginx/sites-enabled/default
...
# Default server configuration
server {
	listen 80 default_server;
	listen 81 default_server;
	listen 82 default_server;
	listen 83 default_server;
	listen 84 default_server;
	listen 85 default_server;
...
$ incus exec myproxy -- systemctl reload nginx
$ 

Then, testing time.

$ incus list -c n4 myproxy
+---------+---------------------+
|  NAME   |        IPV4         |
+---------+---------------------+
| myproxy | 10.10.10.196 (eth0) |
+---------+---------------------+
$ curl 10.10.10.196
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
...
$ curl 10.10.10.196:81
<!DOCTYPE html>
...
$ curl 10.10.10.196:82
<!DOCTYPE html>
...
$ curl 10.10.10.196:85
<!DOCTYPE html>
...
$
3 Likes

It does, indeed in the documentation this line is missing that possibility but in Device options it explicitly said for listen AND connect that you can write it that way :

The address and port to bind and listen (<type>:<addr>:<port>[-<port>][,<port>])

Incus will fill up the rest of the ports.

I didn’t knew that, Incus is so well done!

When you perform port forwarding, you can choose the direction of the forwarding using the bind option. Therefore, when you forward from the container to the host, you specify the range in the container and the starting port on the host.

In other words, you can specify a range and a destination starting port, but not a range to a range. I admit there should be some clarification. The docs use brackets when specifying the ranges which means they are technically correct.

1 Like