Iptables – redirect all incoming HTTPS traffic to another port

httphttpsiptables

I have a Linux Router and two locally hosted pages (running on this server), and I want to redirect all incoming HTTPS traffic to an application running on port 14902, and all incoming HTTP traffic to an application running on port 14901.

enter image description here

A rule like this one (nat table), works perfectly with the incoming traffic on port 80 (HTTP). That means, every page that I request via a Web Browser, is redirected to the application (port).

-A PREROUTING -i eth2 -p tcp --dport 80 -j DNAT --to-destination 192.168.0.1:14901

…but for HTTPS, the same doesn't apply.

-A PREROUTING -i eth2 -p tcp --dport 443 -j DNAT --to-destination 192.168.0.1:14902

Even though I have forced my machine to resolve any DNS names to the IP of my Linux Router (so there's no other way that the Web Browser might perform any verification around the real IP address for the specified domain), by some mechanism regarding SSL certificates or any other sort of technique which I do not know, the Web Browser informs that I must perform login into the network, for every time that I request pages like https://facebook.com or https://youtube.com.

Without forcing the DNS as I mentioned, the Web Browser finds a way to access http://youtube.com, even though I have such rule for incoming traffic with 443 as destination port, and this happens just with YouTube. Just to mention this "fun fact". But ok. Moving on.

enter image description here


  • How could my Web Browser figured out that the remote webserver is declaring "Strict Transport Security", if my Firewall rules do not allow the contact with them?

  • Does the Web Browser performs a HTTP request first, before doing the SSL Handshake, and that's why it informs me about authentication, like a Captive Portal?

  • My main question: Is there any technique that could be applied on IPTABLES/Netfilter, (for example, using raw or mangle tables) that could guarantee that packets with destination port 443, must always be redirected to a specific port, like this example?


I understand the behaviour of asking login on the network, thinking of HTTP requests, since Browsers and OSes have mechanisms of Captive Portal detection, performing HTTP GET for specific pages. But with the right configuration regarding Firewall, thinking of incoming traffic with port 443 as destination, I can't understand why this situation is happening.

I checked the logs for the Nginx Virtual Host (using Self-Signed Certicate), and indeed, there are no requests coming to the application which is running on port 14902.

I know that on mangle table, you can adjust things like MTU and that on raw table, you can apply PREROUTING as well, for packets before connection tracking states. Maybe someone with advanced background on IPTABLES/Netfilter (which is not my case), can mention a possible solution.

Best Answer

Why not use nginx instead?

server {
    listen 80;
    return 301 http://192.168.0.1:14901/$request_uri;
}

server {
    listen 443 ssl;
    return 301 https://192.168.0.1:14902/$request_uri;
}

But your cert probably isn't going to work without hostnames:

server {
    listen 80;
    server_name app1.example.com
    return 301 http://app1.example.com:14901/$request_uri;
}

server {
    listen 443 ssl;
    server_name app2.example.com
    return 301 https://app2.example.com:14902/$request_uri;
}

Use iptables to open ports 80 and 443 and let nginx do its thing.

iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT

If you need UDP, simply add

iptables -A INPUT -p udp -m udp --dport 80 -j ACCEPT
iptables -A INPUT -p udp -m udp --dport 443 -j ACCEPT