I know you can limit number of connections per ip, per time interval etc, but what I am wanting is amount of data.
I'm hosting a socket server, and I thought rather than making it do the processing to check for flooding - offload it to the firewall. I know you can guard against syn flooding attacks, like mentioned here:
http://www.cyberciti.biz/tips/howto-limit-linux-syn-attacks.html
For example:
# Limit the number of incoming tcp connections
# Interface 0 incoming syn-flood protection
iptables -N syn_flood
iptables -A INPUT -p tcp --syn -j syn_flood
iptables -A syn_flood -m limit --limit 1/s --limit-burst 3 -j RETURN
iptables -A syn_flood -j DROP
#Limiting the incoming icmp ping request:
iptables -A INPUT -p icmp -m limit --limit 1/s --limit-burst 1 -j ACCEPT
iptables -A INPUT -p icmp -m limit --limit 1/s --limit-burst 1 -j LOG --log-prefix PING-DROP:
iptables -A INPUT -p icmp -j DROP
iptables -A OUTPUT -p icmp -j ACCEPT
I'm not sure what iptables can do, so the question is a bit vague. But since web-sockets use tcp I should be able to limit number of bytes per second. And flag connections exceeding that limit or just drop them, whatever.
I can't seem to find a good reference on this, as they are all about tracking connections etc, not data transfer. Does anyone know of a good reference or how to do this? Is iptables not a good firewall for this? if not what is?
The kernel-side firewall is the fastest and the most secure software solution (difficult to kill the kernel isn't it?). Using it have also the advantage to use the hardware firewall found on some network controllers.
Iptables is the primary tool for controlling it, but there are many others frontends with easier syntax.
If you want to configure easier, you should use this :.
Keep in mind tracking byte count for each IP can use lot of memory.
In your case I would install ipset, which is developed by the same team of iptables :
#create ipset for accounting with default lifetime 300 secs
ipset create IP_QUOTA_SET hash:ip timeout 300 counters
#create separated rule chain
iptables --new-chain PER_IP_QOUTING
#send packets to chain
iptables -t filter -A INPUT \
-i <in-iface> --dst <ip> \
-p tcp --dport <dstport> \
-j PER_IP_QUOTING
#if ip doesn't exist in the set, add it
iptables -t filter -A PER_IP_QUOTING \
-m set ! --match-set IP_QUOTA_SET src \
-j SET --add-set IP_QUOTA_SET src --timeout 300
#if packet exists in the set, check bytes
#if byte counter > quota then drop packet
iptables -t filter -A PER_IP_QUOTING \
-m set --match-set IP_QUOTA_SET src \
--bytes-gr 1000 -j DROP
#pass other packets (for debug purpose)
iptables -t filter -A PER_IP_QUOTING \
-j RETURN
In this case you can check the list and edit it by ipset command.
To show current list with counters and timeouts :ipset list IP_QUOTA_SET.
STRONG NOTE : iptables is Linux specific and is available since linux 2.4. The kernel implementation along the userspace tools did change in 2.0 and 2.2 previously.
The 3.13 version introduced a new change which will replace ipset; arptables; ebtables; ip6tables, and iptables with a single tool.
As with previous versions, their will be a transition period where frontends like vuurmuur will remain compatible with the kernel, but don't expect to use iptables in the future.
You can try the iptable command mark together with tc (traffic-shaping):http://www.amiryan.org/2009/02/16/traffic-shaping-under-linux-with-tc-and-iptables/.
Related
Got a server exposed to the recent MongoDB ransom scam. https://www.bleepingcomputer.com/news/security/mongodb-databases-held-for-ransom-by-mysterious-attacker/
I closed it down until I fixed this.
What's the easiest way to fix this? Is to add a user?
mongo
use admin
db.createUser( { user: "root", pwd: "password", roles: [ "root" ] } )
Is this enough to avoid getting hacked?
Expanding on #Sammye's comment mongodb has often no password for a database user. This is especially problematic if the database is facing the public internet because, just by trying the right port on the ip adress of your server everyone in the internet could theoretically connect to the database server.
To prevent this it is always a good idea to limit the traffic that can reach your server and its ports by a firewall.
Here is a sample iptables configuration (for ubuntu):
the following commands allow all traffic to localhost and to the ports 22 (ssh), 80 (http) and 443 (https)
# accept local traffic
sudo iptables -A INPUT -i lo -j ACCEPT
# allow established connections
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# allow connections to ports 22, 80, 443
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
these commands block the rest of the traffic:
# drops the rest of the traffic to the server
# sudo iptables -P INPUT DROP
# disables the possibility to route traffic through the server (you may or may not want to use this)
# sudo iptables -P FORWARD DROP
# makes it possible to send data from the server
# sudo iptables -P OUTPUT ACCEPT
Before running any of these iptables commands it is always a good idea to set up a cronjob that resets your iptables configuration every 5 minutes. In that case if something goes wrong (you lock yourself out of the server for example because you forgot to enable port 22 in your firewall) the rules get reset and you can fix the issue.
this is a script from the iptables ubunt wiki to reset the firewall:
https://help.ubuntu.com/community/IptablesHowTo
echo "Stopping firewall and allowing everyone..."
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
when everything is finished and seems to be working do not forget to install the package iptables-persistent (by default the iptables rules only exist until the server is restarted)
sudo apt-get install iptables-persistent
this is by far not a complete guide on how to secure your server with iptables as firewall but I hope that it can get you started.
Now the database is only reachable from the server on not from the public internet anymore. To access your database from the public internet anyways you will have to create a ssh tunnel to your server:
ssh youruser#yourdomain_or_ip_adress -f -N -L 27019:yourdomain_or_ip_adress:27019
-f -N -L 27019 <-- here you define the port that should be used on your machine for the database traffic
yourdomain_or_ip_adress:27019 <-- this is the port that the database runs on on your server
When this is done you should be able to access the database from your server at your local machine at 127.0.0.1:27019.
This is a more general way to secure any application that runs on a server that is exposed to the internet.
There is also an official guide on how to specifically secure mongodb internally you can find it here: https://docs.mongodb.com/manual/administration/security-checklist/
I would like to know your professional opinions on the following rule for iptables. I know it is possible to move cPanel's port but it's not so easy for WHM and some other services etc.
I needed something to route a new private port i.e. 1234 to the service while blocking the default port i.e. 2083. In my head, the following rule does this:
Marks the packets incoming on the private port
Redirects the packets to the actual port
Only accepts marked packets on the actual port
Note: The policies are defaulted to DROP all NEW connections
The rules below are working as expected, but before I go and get too excited that the job is done, I wanted a pro opinion on it first. The rules, and preceding context:
# Policy defaults
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -P FORWARD DROP
# Accept anything to/from localhost
iptables -A INPUT -i lo -j ACCEPT
# Accept anything established/related
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# --------------------------------------------------------------------
# Port forward and block (cPanel)
iptables -A PREROUTING -t mangle -p tcp --dport 1234 -j MARK --set-mark 0x400
iptables -A PREROUTING -t nat -p tcp --dport 1234 -j REDIRECT --to-ports 2083
iptables -A INPUT -p tcp --dport 2083 -m mark --mark 0x400/0x400 -m state --state NEW -j ACCEPT -m comment --comment "cPanel (Secure)"
Im no iptables wizzkid but it seems to work, Is this fairly secure?
Thanks in advance
This is my iptables script which i run in bash. The saving of the configurations is part of the script.
#!/bin/bash
#
# iptables-konfigurasjon
#
# Set default rule to ACCEPT to avoid being locked out
iptables -P INPUT ACCEPT
# Flush all excisting rules
iptables -F
# New default rules
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# localhost:
iptables -A INPUT -i lo -j ACCEPT
# Not entirely shure what this is about....:
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow SSH.
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# Allow http traffic for tomcat:
iptables -A INPUT -p tcp --dport 8080 -j ACCEPT
# Save rules:
/sbin/service iptables save
But, after testing it seems that these rules have no effect after all.
Example: If I comment out the line for allowing traffic to my tomcat server, I can still reach my tomcat server from outside.... even after a reboot.
What's wrong with my script?
BTW: I'm using CentOS 6.
after saving the newly added rules to your iptables, you have to restart the service so that changes take effect.
/sbin/service iptables restart
or
/etc/rc.d/init.d/iptables restart
You can add this in the end of script (for the CentOS):
iptables-save > /etc/sysconfig/iptables
service iptables restart
Problem
Why this happens
iptables functionalities are used by some other services like ufw or firewalld (depending on the distro you are using), which are blocking the changes made by iptables cli.
Solution
All you have to do is just remove the package firewall pkg installed on your machine
for ubuntu (debian distros) using the following command to remove the package
sudo apt purge ufw -y
I was trying to change the incoming interface of the packet using iptables MARK and ip route commands.
I have tried this approach which suggests the use of iptable Mark and iproute2 utilities instead of ROUTE target, but could not find any success changing the incoming interface of the packet in the receiving path.
I have an application 'A' which binds to an interface intfA in linux i.e the application sends and receives packets only on via intfA.
Sending path
In a tunnel based setup, I was able to send packet's out from intfA to tap0 using the following iptable commands:
iptables -t mangle -A OUTPUT -d 8.9.10.11/32 -j MARK --set-mark 1
ip rule add fwmark 1 priority 9000 table 1
My default routing entry in main table is pointing to intfA
In table '1' I have made the default routing table entry point to tap0:
route add default dev tap0 table 1
I could observe from the kernel dmesg logs that the outgoing interface of the packet changed succesfully from intfA to tap0.
In the return path
After tap0 gets the encrypted packet from tunnel, it decrypts it and injects the plain text packet with destination 'a.b.c.d' into the linux kernel via the tap0 interface.
So at the kernel prerouting hook, I see the packet coming with IP = 'a.b.c.d' and with incoming tap0.
Following iptable rules were used to change the incoming interface:
iptables -t mangle -A PREROUTING -d a.b.c.d/32 -j MARK --set-mark 2
ip rule add fwmark 2 priority 8000 table 2
In table '2' I have made the default routing table entry point to intfA:
route add default dev intfA table 2
I tried to log the packets at the PREROUTING hook and the INPUT hook using the following iptable commands:
iptables -t mangle -A PREROUTING -d a.b.c.d/32 -j LOG --log-level 0 --log-prefix "VPN PREOUTING: "
iptables -t mangle -A INPUT -d a.b.c.d/32 -j LOG --log-level 0 --log-prefix "VPN INPUT: "
I was hoping the incoming interface of the packet to be changed from tap0 to intfA between the PREROUTING hook and INPUT hook. But suprisingly the interface doesn't change in both the kernel log trace. I could see the incoming packets marked with mark 2 as well.
From the dmesg log's i confirmed that the Incoming interface still remains as tap0 after the INPUT hook.
I wanted to understand the reason behind this behaviour for the iptables commands I have used. Not sure if I missed anything in iptables commands I used which is causing this issue.
I have the same problem. As a temporary solution I've found that -j TEE target helps:
iptables -t mangle -A PREROUTING [options] -j TEE --gateway IP
In your case, fill [options] and the gateway's IP (intfA address) with your values.
Hey guys in my iptables file I have the following line:
-A INPUT -m state --state NEW -m tcp -p tcp --dport 20000:25000 -j ACCEPT
Because I'm trying to open a range of ports that will need to be open for multiple (Yes THAT many multiple) different minecraft servers.
I know the issue is the IPTables because when I stopped them, I was able to get on the server (Port 20004) But with them on, I can't connect, did I format it right? I even did just
-A INPUT -m state --state NEW -m tcp -p tcp --dport 20004 -j ACCEPT
The second one copying the exact SSH port 22 rule, except the port obviously, any ideas? Thanks!
Did you issue an
-F INPUT
first, if relevant?
You have asked for ideas. If you've not tried this one, you might. IPtables bugs sometimes are not trivial to isolate, are they? However, it can help if you start from a known state, which the -F achieves.
Good luck.
You can try this
#iptables -A INPUT -p tcp --match multiport --dports 20000:25000 -j ACCEPT
You can also use the above rule
iptables -A INPUT -m state --state NEW -m tcp -p tcp --match multiport --dports 20000:25000 -j ACCEPT