Forward port 80 and 443 from WAN to container

Dear all,

I want to run a webserver inside an LXC container. The container is on my Ubuntu 18.04 LTS router. The WAN interface is enp1s0. With the standard setup after LXC init I have access from the lan but not WAN. I have read that the new LXD/LXC has a opportunity to set-up a proxy automatically so that traffic could be forwarded without changing IPTABLES. However, I could not find an explanation of the syntax.
How do I get LXD to do the nexessary modifications to forward port 80 and 443 from enp1s0 to the container?

Thank you

Hi!

Here are the commands to run on the host. You only need the name of the container to perform the setup. In my example I’ll use mycontainer.

lxc config device add mycontainer myport80 proxy listen=tcp:0.0.0.0:80 connect=tcp:127.0.0.1:80

lxc config device add mycontainer myport443 proxy listen=tcp:0.0.0.0:443 connect=tcp:127.0.0.1:443

What we do here is:

  1. We add a proxy device on container mycontainer, giving it an arbitrary name (myport80).
  2. We set it up to listen on all (0.0.0.0) network interfaces on the host, port 80. You can change the IP address to something more specific, if you want to.
  3. We set it up to make connections to the container mycontainer on the 127.0.0.1 (localhost) interface at port 80. PREVIOUS GUIDES SUGGESTED TO USE localhost. DOES NOT WORK ANYMORE; PLEASE USE 127.0.0.1 INSTEAD!

To verify that LXD is listening on port 80 (http), run

$ sudo lsof -i -n | grep http
lxd       2157            root    5u  IPv6 668213      0t0  TCP *:http (LISTEN)
lxd       2157            root    8u  IPv6 668213      0t0  TCP *:http (LISTEN)

To remove a proxy device, run

lxc config device remove mycontainer myport80
4 Likes

Perfect, thank you very much. That worked! Just one more questions: Is there a performance penalty compared to the “traditional” use of iptables with Forward etc. or is the performance the same?

Sorry, stupid question. I just noticed that I seem to need to have both? Here is what I did:
enp1s0 is my WAN interface
-A PREROUTING -p tcp -m tcp -i enp1s0 --dport 80 -j DNAT --to-destination 10.175.162.124:80
-A INPUT -i enp1s0 -p tcp --dport 80 -j ACCEPT
-A FORWARD -p tcp -d 10.175.162.124 --dport 80 -j ACCEPT

Plus the setup that you suggested with the LXC proxy. Is this too complicated? Should I use a different LXC bridge?

Someone else just asked the same question,


There is a way to test, which I describe. I do not have the setup yet to test myself, so feel free to test and report back.

You do not need to add iptables rules.

The two commands that start with lxc config device add mycontainer myport80 proxy, are commands that set up a LXD Proxy Device. One command is for port 80, the other for port 443.

There is no need to use different network settings like a different bridge.

Hello Simos, in ‘listen’ can the destination domain of the packet be used instead of IP (0.0.0.0) and thus use this feature in the same way as we would use in a reverse proxy in nginx?

In listen you put a valid IP address of the host, or 0.0.0.0 to specify all interfaces.
Ideally, it is better to put the explicit public IP address of the host and not 0.0.0.0.

When you mention destination domain, is that a domain name? If so then no.

1 Like

That’s right, “domain name” such as “www.test.com”.
But anyway thank you very much @simos

If the hostname resolves to the appropriate host IP address, then you can use it instead.

lxc config device add mycontainer myport80 proxy listen=tcp:0.0.0.0:80 connect=tcp:localhost:80
lxc config device add mycontainer myport443 proxy listen=tcp:0.0.0.0:443 connect=tcp:localhost:443

i have domain name which resolve IP, but can i use both IPv4 & IPv6

Can an addition port for an api be added the same way?
Currently I route all 80 and 443 to a proxy container and then from proxy container to the desired website container… using real_ip_header X-Real-IP; set_real_ip_from proxy.lxd;
I have several several containers each with websites on them. At the moment I use 80 and 443 and it works fine, but on a new website I’m working on (running a nodejs app) I need to pass additional information from port 8117, to the website front end viewable to public.
currently I do this by iptable forward port 8117 to the desired container. Problem I’m having is when I install an ssl cert for the website port 8117 information is not longer viewable.
`server {
listen 80 proxy_protocol;
listen [::]:80 proxy_protocol;

    server_name apache1.example.com;

    location / {
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_pass http://apache1.lxd;
    }

    real_ip_header proxy_protocol;
    set_real_ip_from 127.0.0.1;

}`


Hi!

If I understand correctly, the nodejs container has to be both accessible by the front-end container BUT also from the Internet? If that is the case, can you describe me a simple example so that I can use and duplicate the issue?

If the nodejs container is ONLY accessible either from the internet, or the front-end container, then it is much simpler.

Hi simos,

the container with the website files are in folder /var/www/html (default)

The nodejs app connects to another app running and pulls information from port 8117 and displays it on the website front end at /var/www/html (default) …these are static pages except for the information displayed via port 8117.

So when someone goes to the website, they view the static frontend pages and the live streaming data coming from 8117. Everything works fine when the site is run on “http” , but when its run on “https” that the live stream info is not displayed.

I hope I’m explaining it for some clarity to you. Just to recap…I have a container named “proxy” and I route all 80 and 443 to it. The proxy container has several virtual blocks that point to the other lxd containers. The other containers are the ones hosting the website frontends and running the various apps pushing info on 8117. I just need to figure out how to allow the reverse proxy to display information from 8117

| proxy (lxd container) | —> | lxd container 1 ( website 1) has live stream info 8117 |
—> | lxd container 2 ( website 2) has live stream info 8118 |
—> | lxd container 3 ( website 3) has live stream info 8119 |

so at the moment all website work fine on “http” just not on “https”

currently I use this and all the info displays correctly on “http”
sudo iptables -t nat -A PREROUTING -p tcp -i ens18 --dport 8117 -j DNAT --to-destination 10.130.57.223:8117
sudo iptables -t nat -A PREROUTING -p tcp -i ens18 --dport 8118 -j DNAT --to-destination 10.130.57.25:8118
sudo iptables -t nat -A PREROUTING -p tcp -i ens18 --dport 8119 -j DNAT --to-destination 10.130.57.79:8119

Is this URL http://10.130.57.223:8117 used on your front-end? Most likely not, because it is obviously not addressable from the internet and you mentioned it works for http. You use a hostname for this. If you want to use https in addition to http, then you need to specify another port for https.

Alternatively, you could use a service like https://www.softwaretestinghelp.com/ngrok-alternatives/