this post was submitted on 11 Sep 2023
14 points (88.9% liked)

Selfhosted

40329 readers
426 users here now

A place to share alternatives to popular online services that can be self-hosted without giving up privacy or locking you into a service you don't control.

Rules:

  1. Be civil: we're here to support and learn from one another. Insults won't be tolerated. Flame wars are frowned upon.

  2. No spam posting.

  3. Posts have to be centered around self-hosting. There are other communities for discussing hardware or home computing. If it's not obvious why your post topic revolves around selfhosting, please include details to make it clear.

  4. Don't duplicate the full text of your blog or github here. Just post the link for folks to click.

  5. Submission headline should match the article title (don’t cherry-pick information from the title to fit your agenda).

  6. No trolling.

Resources:

Any issues on the community? Report it using the report flag.

Questions? DM the mods!

founded 1 year ago
MODERATORS
 

I am trying to set up a reverse proxy server, with TLS passthrough.

I am behind CGNAT, so I cannot forward any ports from my home server. So, my current workaround was that I connected my home server to a VPS via WireGuard and used Nginx Proxy Manager (NPM) to proxy services running on different docker containers to the VPS, so that they are accessible publicly. But now I want to use TLS passthrough for better privacy. But I cannot find any guides for my case.

I need help with 2 issues, basically. Let's take a look at my passthrough.conf file, which I have included in nginx.conf file.

stream {
    # Listen for incoming TLS connections on service1.domain.me
    server {
        listen 443;
        proxy_pass service1.domain.me;
        proxy_ssl on;
        proxy_ssl_protocols TLSv1.2 TLSv1.3;
        proxy_ssl_name $ssl_preread_server_name;
    }

    # Listen for incoming TLS connections on service2.domain.me
#    server {
#        listen 443;
#        proxy_pass service2.domain.me;
#        proxy_ssl on;
#        proxy_ssl_protocols TLSv1.2 TLSv1.3;
#        proxy_ssl_name $ssl_preread_server_name;
#    }

    # Define the backend server for service1.domain.me
    upstream service1.domain.me {
        server homeserverIP:port;
    }

    # Define the backend server for service2.domain.me
#    upstream service2.domain.me {
#        server homeserverIP:port;
#    }
}

The services are running in docker containers on different ports. When I used two server blocks and two upstream blocks, I got this error while testing NGINX config: nginx: [emerg] duplicate "0.0.0.0:443" address and port pair in /etc/nginx/passthrough.conf:13. So, I commented out the other server block and tested it again. The test was successful, but NGINX failed to restart. When I checked the systemctl status I saw: nginx[2480644]: nginx: [emerg] bind() to 0.0.0.0:443 failed (98: Address already in use). This is because I am already hosting multiple WordPress sites on this VPS.

Here's my nginx.conf file:

user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
        worker_connections 768;
}

http {

        sendfile on;
        tcp_nopush on;
        types_hash_max_size 2048;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;


        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        gzip on;

        gzip_vary on;
        gzip_proxied any;
        gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;

        client_max_body_size 100M;
        server_tokens off;

}

#include /etc/nginx/passthrough.conf;

I do not know much about NGINX configuration, any help or article links would help.

top 19 comments
sorted by: hot top controversial new old
[–] towerful@programming.dev 7 points 1 year ago (1 children)

As has been mentioned, put the WordPress sites on different internal ports or different internal IPs (easier if they are dockerised on a docker network).
Then have nginx have the external 80/443 port binds, and reverse proxy to the WordPress instances.

This is really handy for nginx config files
https://www.digitalocean.com/community/tools/nginx

[–] nutbutter@discuss.tchncs.de 1 points 1 year ago (1 children)

This looks like a really great tool, but I cannot seem to find TLS pass through options in here. Or maybe I am too dumb to understand. I do not want the proxy server to generate or keep any certificates, all that will be done by my home server. All I want the proxy server to do is pass through the TCP connection.

[–] towerful@programming.dev 2 points 1 year ago (1 children)

If you are forwarding to multiple services, TCP proxying isnt going to work.
The proxy server has to know where to send the connection, so it has to be protocol-aware. In this case, http/https is the protocol.

Luckily TLS/HTTPS has functionality for this without having to terminate encryption, called SNI.

Here is an article using SNI and nginx.
https://gist.github.com/kekru/c09dbab5e78bf76402966b13fa72b9d2

[–] nutbutter@discuss.tchncs.de 1 points 1 year ago (1 children)

Thanks. So, I just have to put this stream block in my nginx.conf file and everything will work? Do I still have to use reverse proxy for my existing WordPress sites? Or can they stay normally configured?

[–] towerful@programming.dev 2 points 1 year ago

If they are running on the same server as nginx, then they will need to be proxied as well.
Only 1 service can bind to a port. So if the webserver doing wordpress is bound to 80/443, nginx will not be able to acquire the port.
Hence why reverse proxying. Nginx binds 80/443, then forwards to other services on arbitrary ports

[–] SheeEttin@lemmy.world 6 points 1 year ago* (last edited 1 year ago)

Only one service can bind to each address-port pair, as the message suggests. Either pick a different one, or use nginx to proxy the wordpress service too.

[–] Decronym@lemmy.decronym.xyz 4 points 1 year ago* (last edited 1 year ago)

Acronyms, initialisms, abbreviations, contractions, and other phrases which expand to something larger, that I've seen in this thread:

Fewer Letters More Letters
CGNAT Carrier-Grade NAT
HTTP Hypertext Transfer Protocol, the Web
HTTPS HTTP over SSL
IP Internet Protocol
NAT Network Address Translation
SSL Secure Sockets Layer, for transparent encryption
TCP Transmission Control Protocol, most often over IP
TLS Transport Layer Security, supersedes SSL
VPN Virtual Private Network
VPS Virtual Private Server (opposed to shared hosting)
nginx Popular HTTP server

[Thread #135 for this sub, first seen 12th Sep 2023, 10:35] [FAQ] [Full list] [Contact] [Source code]

[–] qjammer@lemmy.ml 3 points 1 year ago (1 children)

I am running a similar setup to yours. The issue is that only one server block can listen to an address+port pair. You ought to do something like this:

map $ssl_preread_server_name $proxy_backend_router {
        serviceA.example.com    upstreamA:12346;
        serviceB.example.com    upstreamB:12346;
        default $ssl_preread_server_name.invalid_proxy:443;
}


server {
        listen 443;
        ssl_preread on;
        proxy_pass $proxy_backend_router;
}
[–] nutbutter@discuss.tchncs.de 1 points 1 year ago (1 children)

Can you link some documentation or a guide that can explain all this?

[–] qjammer@lemmy.ml 2 points 1 year ago

The nginx documentation for the ssl preread module has an almost identical example.

[–] MigratingtoLemmy@lemmy.world 2 points 1 year ago* (last edited 1 year ago) (1 children)

Hi OP,

I don't know how to do TLS pass-through, but I think you could just run NAT (configure the firewall on your VPS) and host your reverse proxy at home. No need for TLS pass-through in such a case, unless you absolutely need to host the proxy on the VPS.

Cheers

[–] nutbutter@discuss.tchncs.de 2 points 1 year ago (1 children)

I am not sure how to do that. Can you, please, link a guide or any documentation? Does this method prevent the VPS provider from looking into the data being passed through?

[–] MigratingtoLemmy@lemmy.world 2 points 1 year ago (1 children)

I don't have any guide (haven't looked for one). The concept is simple:

  1. Configure Wireguard server on the VPS.
  2. Connect to server using your router/home firewall as a client (I believe you've done this already).
  3. Configure nftables or iptables to forward traffic coming from a certain IP/port through your VPN connection to your router.
  4. Since you have hosted your proxy at home, that's where TLS termination happens, which means your traffic is encrypted in transit (NAT does not decrypt packets). So yes, you're (in theory) safe from the VPS provider.

I believe there are ways to encrypt one's RAM on a VPS but you likely don't need it here, and that might be beyond the scope of this discussion anyway.

Cheers. I was given this idea by another person on Lemmy, I'm just pushing this wonderful idea forward.

[–] nutbutter@discuss.tchncs.de 2 points 1 year ago (1 children)

I have configured WireGuard server on the VPS, yes. But I am not connecting to it using my router. I am just using a wg config file on my home server to connect to it. And do I configure nftables or iptables on the VPS? Because the traffic from my home server is already set to forward to the VPS using wireguard. The proxy is set up on the VPS, not home server. I cannot change any settings on my router because I am behind CGNAT.

[–] MigratingtoLemmy@lemmy.world 2 points 1 year ago (1 children)

Well, it doesn't matter if you configure the wireguard client on the router or the server.

Running your proxy at home instead of on the VPS makes it possible for you to terminate SSL at home, inside your LAN, which means no need for TLS pass-throughs.

nftables is recommended by Debian, but I suppose either one will work just fine.

I'm asking you to configure NAT on your VPS so as to forward traffic from the wider Internet, through your VPS into your wireguard tunnel. Obviously, I'm assuming you're following security practices on the VPS so as to not compromise your home network. The configuration you have on your server is fine, since that's meant for outbound traffic.

You can absolutely run a Wireguard client on your router, regardless of whether you are behind CG-NAT or not. It's a different story if your router doesn't even let you run extra software on top. That's a different conversation.

Cheers.

[–] nutbutter@discuss.tchncs.de 2 points 1 year ago (1 children)

Thanks. I understand, now.

And yes, my router does not have any option to configure a VPN.

[–] MigratingtoLemmy@lemmy.world 1 points 1 year ago

Hey, sorry if I came across a bit curt in the previous message.

Can you do a DMZ and run your own router behind your ISP's router?

[–] Pulp@lemmy.dbzer0.com -3 points 1 year ago (1 children)

Just use cloudflare tunnels

[–] nutbutter@discuss.tchncs.de 1 points 1 year ago

There is TLS termination at the Cloudflare's backend servers, so theoretically, they can look at all the data going through.