iptables: block incoming but allow outgoing - block

I use an ubuntu server to power my home network. the server is directly connected to the internet via the interface wan0. on the intranet site it uses a bridge br0 (which joins lan0 and wlan0).
to block incoming requests from the internet i use iptables. it works fine to block incoming requests, but i have the issue, that the server itself (not the clients of the intranet) is no longer able to connect to the internet (e.g. with ping 9.9.9.9).
the used iptable rules look like the following:
*filter
# Global policies (drop the whole input)
:INPUT DROP [0:0]
:FORWARD ACCEPT [12:948]
:OUTPUT ACCEPT [52:5479]
# Allow loopback for device local communication
--append INPUT --in-interface lo --jump ACCEPT
# Allow all input from the intranet
--append INPUT --in-interface br0 --jump ACCEPT
# Allow ssh on port 22 from the wan
--append INPUT --in-interface wan0 --protocol tcp --dport 22 --match conntrack --ctstate NEW,ESTABLISHED --jump ACCEPT
# Allow ping from the wan
--append INPUT --in-interface wan0 --protocol icmp --icmp-type echo-request --jump ACCEPT
COMMIT
*nat
# Global policies
:PREROUTING ACCEPT [362:62516]
:INPUT ACCEPT [57:12612]
:OUTPUT ACCEPT [43:4250]
:POSTROUTING ACCEPT [31:2839]
# NAT traffic to the wan
--append POSTROUTING --out-interface wan0 --jump MASQUERADE
COMMIT
can somebody please help me find the issue or which rule i do have to add, so the servers requests are able to get into the internet again?

Related

HTTP iptable PREROUTING rule is not working

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/

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.

Setting up iptables for a hostapd wifi login page

I need some custom iptables for a login page of my wifi hotspot on my raspberry pi. I want an http login page: this is how it should work, I just don't know how to configure the iptables.:
Any connections on an ip address that is not already logged in, should be redirected to the pi's port 8181 (the server for my login page).
Any connections on an ip address that is logged in should be allowed to access the outside internet.
Any connections initially requesting the pi's port 8181 should be allowed.
How should I set this up with iptables?
Thanks!
I've found the following article very helpful when learning iptables:
http://wiki.centos.org/HowTos/Network/IPTables
Basically you can start with a something similar to:
# iptables -P INPUT ACCEPT
# iptables -F
# iptables -A INPUT -i lo -j ACCEPT
# iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# iptables -P INPUT DROP
# iptables -P FORWARD DROP
# iptables -P OUTPUT ACCEPT
This will block pretty much everything other than SSH, outgoing connections, and connections that are previously established (ie from previous outgoing connections)
Once that is in place you need to do the redirection:
http://proghowto.com/iptables-redirect-port-80-to-port-8080
And finally you need to run something like the following for each ip that gets authenticated:
# iptables -A INPUT -s 192.168.0.4 -j ACCEPT

iptables allow whm mail port 25

Trying to understand iptables (I have cPanel installed on VPS) and having a little play so may sound like a silly question what I am doing.
I have copied the default iptables config to backup (in case goes wrong to restore) and created custom iptables config (/etc/sysconfig/iptables) were I DROP INPUT/OUTPUT/FORWARDING (so everything).
I then managed to get all the ports I want access to required working (incoming/outgoing HTTP/s/SSH/FTP etc) apart from emails (:25). I am using Roundcube and using the below config for emails but emails can not be sent/received on my server (works if I restore default config (ACCEPT everything) so apart from port :25 is there any other ports I need to allow access to for mail to be sent knowing everything has been dropped?). I am using below config for email in my custom (/etc/sysconfig/iptables):-
-A INPUT -p tcp --dport 25 -m state --state NEW,ESTABLISHED -j ACCEPT
-A OUTPUT -p tcp --sport 25 -m state --state ESTABLISHED -j ACCEPT
-A OUTPUT -p tcp --dport 25 -j ACCEPT
-A INPUT -p tcp --sport 25 -m state --state ESTABLISHED -j ACCEPT
IP is a bidirectional communication, when you receive a mail, packets are sent on your server on port 25, and you will send response packet on a arbitrary allocated port number (determined during connection establishment).
So, common rule on iptables are :
Accepting packet on input from a specified port (25 for mail) whatever the state of connection
-A INPUT -p tcp --dport 25 -j ACCEPT
Accepting to send back packets for all established connection whatever the destination port.-A OUTPUT -p tcp -m state --state ESTABLISHED -j ACCEPT
Now, if you want to send mail to a server, you have to allow packet to go out to port 25 and allow incoming all established connection.
-A INPUT -p tcp -m state --state ESTABLISHED -j ACCEPT
-A OUTPUT -p tcp --dport 25 -j ACCEPT
Another idea , will be to log packets that should be dropped.
put log line a the end of all chain's rules.
iptables -A INPUT -p tcp -j LOG --log-prefix "INPUT PACKET DROPPED "
iptables -A OUTPUT -p tcp -j LOG --log-prefix "OUTPUT PACKET DROPPED "
With that, you will see in /var/log/message (or with dmesg) a line for each packet reaching the end of chain's rule and beeing dropped.

with iptables forwarding port to other client but with recognition of original sender ip

I have a firewall (based on iptables) at dedicated ubuntu server.
I have several LAN Clients.
At one of my LAN Clients I am running software where I can restrict acces based on IP.
For me it is important that I can restrict that by using WAN IPs so not LAN IPs.
I have configured my firewall so that a/one port is forwarded to a LAN client which work good (solution found at stackoverflow). So far no problems.
However at the LAN client I do not see the IP of external sender but - I think due to the forwarding - the client sees that the packet is coming from my LAN server.
Question is: how to forward a port on my server to another LAN IP with different port, but so that the LAN client recognizes the external IP of the packet.
Lets make it more clear:
server LAN IP: 192.168.1.10
server port: 8080
should be forwarded to:
client LAN IP: 192.168.1.20
client LAN port: 8000
With iptables I have:
iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 8080 -d 192.168.1.10 -j DNAT --to 192.168.1.20:8000
iptables -A FORWARD -p tcp -d 192.168.1.20 --dport 8000 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A POSTROUTING -p tcp --dport 8000 -d 192.168.1.20 -j SNAT --to 192.168.1.10
As written that works, but when f.i. someone at IP 88.77.66.55 sends a packet then my LAN client (192.168.1.20) sees that the packet is coming from my LAN server (192.168.1.10) and unfortunately not from 88.77.66.55.
Can I fix that...?
Your last rule is the same as a MASQUERADE rule.
eg:
iptables -t nat -A POSTROUTING --out-interface eth0 -j MASQUERADE
With MASQUERADE or SNAT, you are modifying the source-IP address as it goes through the first server. The 2nd server sees the packet and sends it's response back to that IP, which is then sent back to the client.
However, the server sees request as coming from 192.168.1.10 - because that's where it's coming from.
client > gateway > iptables-router > server (sees .10) > iptables-router > gateway > client
If you remove the MASQUERADE/SNAT, the server sees the real IP, but when it sends the reply, the packet is going to it's default gateway (default route) which is probably your router or a gateway at your data center. The client gets a response back from an IP address it doesn't know about, and doesn't know what to do with it, so it looks like it's not working. Alternatively, the gateway/rputer sees a SYNACK with no associated connection and drops the packet.
client > gateway > iptables-router > server > gateway (DROP) or > client (DROP)
If you want the server to get the real IP of the client, here are two common ways to make it work:
Set the gateway (default route) of the server to the IP address of the iptables machine (ie: the machine you are running these iptables rules on). In this case, the server sends all external traffic (ie: a response to a random IP address from the internet) to the MAC address of the iptables machine, which is waiting for a reply. iptables will send it back to the client. The webserver machine is behind the iptables machine, using the iptables machine as a router.
client > gateway > iptables-router > server(real IP) > iptables-router > gateway > client
Use an HTTP proxy like nginx which will work the same way you have it working now, with the client only seeing the internal .10 address. However, because it's a proxy, it can send an HTTP header like X-Original-IP-Address: 123.456.789.012 containing the real IP address of the client.
client > gateway > iptables-router > server (sees X-Original-IP header) > iptables-router > gateway > client
Best Regards,
Neale
Let us define:
{source address} - packet sender (some remote address)
{interface address} - packet receiver (firewall external address)
{local address} - packet end point receiver local network address
{local gateway} - firewall local address
{proto block} - IP protocols limitation (i.e. -p tcp -m tcp --dport xxxx)
1. If you want the client to see ip address of packet source - do that:
IPTABLES -t nat -A PREROUTING -s {source address} -d {interface address} {proto block} -j DNAT --to-destination {local address}
IPTABLES -A FORWARD -d {local address} -j ACCEPT
Do not forget to make:
echo "1" > /proc/sys/net/ipv4/ip_forward
It will enable packets forwarding.
In this case, your end point will see original ip address, however, it will try to respond to default gateway, if this address is not in local network range, add:
route add {source address} gw {local gateway}
this will tell your endpoint to send packets for {source address} via {local gateway} (or reply back).
2. You do not want endpoint to see original ip address and do not want to modify routing tables, then add
IPTABLES -t nat -A POSTROUTING -s {source address} -j MASQUERADE
In this case, LAN client will see only {local gateway} address.
In any case, do not forget to masquerade all packets that are going from your local network to remote addresses by:
IPTABLES -t nat -A POSTROUTING !-d 192.168.0.0/16 -j MASQUERADE
You want to keep source address and destination address for further processing. In this case, your {local gateway} will be just a part of packet routing and {local address} has to be just a next hop - use policy routing for that.
First, add your own routing table with lower than 252 tag to /etc/iproute2/rt_tables
Then - you can add rule for {source address} directly to rules set or mark packets from {source address} - both methods will lookup your custom routing table for that packets:
ip rule add from {source address} table custom_table
or
iptables -t mangle -A PREROUTING -s {source address} -j MARK --set-mark 1
ip rule add fwmark 1 table custom_table
And then, make {local address} next hop gateway for these packets:
ip route add default via {local address} table custom_table
Of course, POSTROUTING chain will be applied just before packet exit and you can shape your source address if needed.
Just remove last rule (do not do SNAT).
Or restrict SNAT alloving only masquarading of your LAN clients by adding -o eth0 condition (assuming eth0 is external interface):
iptables -t nat -A POSTROUTING -p tcp -o eth0 --dport 8000 -d 192.168.1.20 -j SNAT --to 192.168.1.10