HTTP iptable PREROUTING rule is not working - iptables

I'm trying to understand iptables and can't seem to redirect traffic at all. The target is to redirect traffic form port 4567 to 8443 and have a (local) program listen on the latter.
I've written a short script to make sure I flush and restart the iptables each time I change the rule:
#!/bin/bash
iptables -t nat -F
iptables -t nat -A PREROUTING -p tcp --dport 4567 -j REDIRECT --to-ports 8443
sudo /sbin/iptables-save
I've also setup the ip_forwarding (although I'm not entirely sure whether I need that):
sudo echo "1" > /proc/sys/net/ipv4/ip_forward
I'm running this simple python script to test the routing. The site is made as to allow http requests on any port.
import requests
r = requests.get("http://portquiz.net:4567")
print(r.status_code)
As well as checking if any packets / bytes pass through the prerouting by looking at the output of iptables -t nat --list -v
Chain PREROUTING (policy ACCEPT 4 packets, 560 bytes)
pkts bytes target prot opt in out source destination
0 0 REDIRECT tcp -- any any anywhere anywhere tcp dpt:4567 redir ports 8443
Both the iptables and the python script are on the same machine (my laptop).
The python request seems to be going through without problems, and does not seem to be intercepted by the prerouting policy.
I'm running on the latest ubuntu 20.02
This is the output of the iptables-save, in case it's useful:
# Generated by iptables-save v1.8.4 on Tue Nov 10 13:20:02 2020
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A PREROUTING -p tcp -m tcp --dport 4567 -j REDIRECT --to-ports 8443
COMMIT
# Completed on Tue Nov 10 13:20:02 2020
# Generated by iptables-save v1.8.4 on Tue Nov 10 13:20:02 2020
*filter
:INPUT ACCEPT [16727:8538288]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [16979:3211690]
COMMIT
# Completed on Tue Nov 10 13:20:02 2020

One needs to pay close attention between local packets, and network packets, when using iptables.
Local packets are packets created on the local machine, whereas network packets are packets received. PREROUTING works on network packets, for instance what you would get on a router device. Since in this case it's all local, then one must use OUTPUT instead of PREROUTING to redirect the packets.
The necessary rule is therefore.
iptables -t nat -A OUTPUT -p tcp --dport 4567 -j REDIRECT --to 8443
I have found this picture to be very useful:
Which comes from this article:
https://danielmiessler.com/study/iptables/

Related

UFW port forwarding does not work with my coturn set up

I am trying to receive data on port 443 and forward that to my coturn server listening to port 5349.
I want this set up so that my webRTC app can connect over 443 but without my coturn server having root access(for privilege port 443).
In my /etc/ufw/before.rules I have below entries
*nat
:PREROUTING ACCEPT [0:0]
-A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 5349
COMMIT
When I test my turn setup at https://test.webrtc.org/ using 443 port I get:
Udp disabled
Relay connectivity timed out
Reflexive connectivity timed out
But using using port 5349 it seems to work.
I have all needed ports open in ufw. I tried with ufw disabled too.
Do I need to add any other changes for port forwarding like adding entry OUTPUT(which I don't know how to add, though).
Do I need to add the rule entry for IPv6 too (/etc/ufw/before6.rules)?
I added these to the before.rules file
*nat
:PREROUTING ACCEPT [0:0]
-A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 5349
-A PREROUTING -p udp --dport 443 -j REDIRECT --to-port 5349
:OUTPUT ACCEPT [0:0]
-A OUTPUT -o lo -p tcp --dport 443 -j REDIRECT --to-port 5349
-A OUTPUT -o lo -p udp --dport 443 -j REDIRECT --to-port 5349
COMMIT
I am not sure if it is ok. But at the moment this seems to work. I am still open for suggestion. Please give me suggestions to improve what I have done so far

HTTP Flood on Tomcat server causing issues

I am getting hit with small HTTP floods on my apache server running port 80 which is proxying tomcat on port 8080.
Now what is happening is this is causing tomcat to create 100s - 1000s of sessions depending on how many clients get passed the cloudflare firewall(s) and my server ones (I have libapache2-mod-qos installed for my Apache server).
IPTABLES:
/sbin/iptables -A INPUT -p tcp -m connlimit --connlimit-above 111 -j REJECT --reject-with tcp-reset
/sbin/iptables -A INPUT -p tcp --tcp-flags RST RST -m limit --limit 2/s --limit-burst 2 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --tcp-flags RST RST -j DROP
/sbin/iptables -A INPUT -p tcp -m conntrack --ctstate NEW -m limit --limit 60/s --limit-burst 20 -j ACCEPT
/sbin/iptables -A INPUT -p tcp -m conntrack --ctstate NEW -j DROP
iptables -A INPUT -p tcp --dport 80 -m hashlimit --hashlimit-upto 50/min \
--hashlimit-burst 500 --hashlimit-mode srcip --hashlimit-name http -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j DROP
example:
Now this is causing major issues for me and if someone could help shed some light on how to get around this I would be greatful.
mod-qos conf:
<IfModule qos_module>
# handle connections from up to 100000 different IPs
QS_ClientEntries 100000
# allow only 50 connections per IP
QS_SrvMaxConnPerIP 10
# limit maximum number of active TCP connections limited to 256
MaxClients 256
# disables keep-alive when 180 (70%) TCP connections are occupied
QS_SrvMaxConnClose 180
# minimum request/response speed
# (deny slow clients blocking the server, keeping connections open without requesting anything
QS_SrvMinDataRate 150 1200
</IfModule>
As far as you know is this legitimate traffic and not part of a DOS / DDOS?
I assume with cloudflare involved it is not however if so then it is best to have an IPS inspect the traffic at an application level and to deny it based on a matching attack signature.
If ligitmate then you will need to assess how the tomcat application is operating based on its code and logs being produced.
Maybe the Tomcat application is requiring the clients to send this data inbound.

SSH tunnel <--> iptables NAT port forwarding - HOWTO?

I need to set up access to the HTTP(S) servers on devices like KVMs and PDUs on a private network (192.168.0.0/24). I must get through an isolated network (10.0.0.0/8) limited to ports 22 and 443. I have a dual-NIC Linux server inside the network that serves as a gateway to the private network. See diagram Here:
Network Diagram
I need to use a forward SSH tunnel to get to the Linux gateway, then use iptables NAT to route HTTP(s) traffic to the web frontends on the devices.
I've observed with both tcpdump and iptables trace that the inbound HTTP(s) request through the SSH tunnel shows up on interface lo , not eth1 as one might expect.
This has led me to come up with the following nat and filter rules:
*nat
-A PREROUTING -i lo -p tcp -m tcp --dport 8080 -j DNAT --to-destination 192.168.0.100:80
-A PREROUTING -i lo -p tcp -m tcp --dport 8081 -j DNAT --to-destination 192.168.0.101:443
-A POSTROUTING -d 10.0.0.0/8 -o lo -j SNAT --to-source <10.gateway_IP>
COMMIT
*filter
:INPUT ACCEPT [37234:5557621]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [26648:27864039]
-A FORWARD -d 192.168.0.0/24 -p tcp -m tcp --dport 80 -j ACCEPT
-A FORWARD -d 192.168.0.0/24 -p tcp -m tcp --dport 443 -j ACCEPT
COMMIT
So, when I set up the tunnel with:
ssh -L 8080:<gateway>:8080 <user>:#<gateway>
Then making sure on the gateway:
$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
and then execute http://localhost:8080,
The packets make it out of the tunnel onto the gateway, out of interface lo, but iptables doesn't seem to forward it to the destination in the PREROUTING rule. stderr from the tunnel returns "Connection refused."
What am I missing?

How to record the packets after iptables?

I want to record the packets (using tcpdump) after iptables, but it seems that tcpdump will record all the packets. I don't want the packet dropped by iptables.
Is there any way to
record the packets after iptables? or
output the packets (processing by iptables) into pcap/log file?
Thanks.
Tcpdump acts before iptables for inbound traffic, but you can use iptables "NFLOG" extension to reach your goal: http://ipset.netfilter.org/iptables-extensions.man.html#lbDI
Using "NFLOG" destination you can log desired packets to userspace application, and that's where tcpdump belongs (you can also assign traffic to a specific group and then tell tcpdump to listen from it).
Webserver (very basic) example, let's pretend you are accepting http/https traffic and dropping ssh:
#BASIC RULES
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j DROP
#NFLOG REDIRECT ONLY HTTP TRAFFIC
iptables -A INPUT -p tcp --dport 80 -j NFLOG
#TCPDUMP ONLY ON MATCHED TRAFFIC (=HTTP)
tcpdump -i nflog

Understanding iptables rate limit

I am new to iptables and I was trying to make sure I understand this statement.
iptables -t nat -A PREROUTING -p tcp -d 5.5.5.5 --dport 25 -m limit --limit 20/min --limit-burst 25 -j ACCEPT
iptables -t nat -A PREROUTING -p tcp -d 5.5.5.5 --dport 25 -j DROP
If an address connects to 5.5.5.5 more than 25 times in 20 minutes block that ip?
You're close. This isn't on a TCP-connection level, it's on a packet level. To deal with connections instead of packets - you'd want to use the state module.
See: https://www.debian-administration.org/article/187/Using_iptables_to_rate-limit_incoming_connections
The negotiation of TCP connections alone is already many packets. See: http://www.inetdaemon.com/tutorials/internet/tcp/3-way_handshake.shtml
These 2 rules state - for all ethernet devices -> if protocol is tcp, destination ip address is 5.5.5.5, and destination port is 25 limit incoming packets to 20 per minute with a burstable amount of an additional 25 per minute. Drop any over this limit.
You might want to look at fail2ban: it will block multiple failed connections. It works for SSH and can be configured for other protocols.