4

I'd like to know if there's any holes/flaws in this firewall setup. I want to lock down the server as much as possible so it is impossible to hack in to. The only services running are openvpn and ssh.

#!/bin/sh
#
# iptables example configuration script
#
# Flush all current rules from iptables
#
iptables -F

#
# Set default policies for INPUT, FORWARD and OUTPUT chains
#
iptables -P INPUT DROP                
iptables -P FORWARD DROP
iptables -P OUTPUT DROP

#
# Allow SSH connections on tcp port 8888 
#
iptables -A INPUT -i venet0 -p tcp --dport 8888 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o venet0 -p tcp --sport 8888 -m state --state ESTABLISHED -j ACCEPT

#
# Set access for localhost
#
iptables -A INPUT -i lo -j ACCEPT

#
# Accept connections on 1194 for vpn access from client
#
iptables -A INPUT -i venet0 -p udp --dport 1194 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o venet0 -p udp --sport 1194 -m state --state ESTABLISHED -j ACCEPT

#
# Apply forwarding for OpenVPN Tunneling
#
iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -s 10.8.0.0/24 -j ACCEPT     
iptables -t nat -A POSTROUTING -o venet0 -j SNAT --to-source 69.147.244.199   
iptables -A FORWARD -j REJECT

#
# Enable forwarding
# 
echo 1 > /proc/sys/net/ipv4/ip_forward

#
# List rules
#
iptables -L -v
9
  • 2
    No. Well, just answering the question in the title. There is no completely secure anything. It would be more secure if you dropped all packets. HHOS ;)
    – d-_-b
    Commented Apr 28, 2011 at 7:56
  • Even then it's not 100% secure. The only way to secure it 100% is to disconnect it, and store it in a bank vault.
    – Majenko
    Commented Apr 28, 2011 at 8:41
  • 1
    And even then, it's not 100% secure. Security is not a destination, it's a process. You need to have procedures in place to constantly review the condition of your server... monitor logs, etc. Even this is only preventative. Personally, I feel the best course of action is to assume that your server will be compromised, and put plans in place to quickly and effectively detect and mitigate the compromise, rather than building walls that will have little effect in reality.
    – gerryk
    Commented Apr 28, 2011 at 8:52
  • 5
    "The only truly secure computer is one buried in concrete, with the power turned off and the network cable cut."
    – grawity
    Commented Apr 28, 2011 at 8:53
  • @grawity what if it was a laptop with wifi and a charged battery with a bios set to turn it on at a specific time. Still not secure ;)
    – Keltari
    Commented Jan 12, 2015 at 20:34

3 Answers 3

4

No. No firewall is completely secure. As long as there is a single port open you are vulnerable to attack.

It is, however, about as secure as you can make it given the circumstances.

It's good to see you're running SSH on a different port to standard.

If the computer is connected to the Internet then it cannot be 100% un-hackable. If there is a flaw in OpenVPN or SSH then an attacker could still gain access through those means. And, the firewall is only as strong as the passwords used on the protocols you pass through that firewall.

Make sure you have really strong passwords. Even better - don't just rely on passwords, but rely on a combination of password and key, so if someone does get your password it's not going to do them much good. And maybe restrict where you're allowing the connections to SSH and OpenVPN to come from - stop any connections from places like China, North Korea, etc.

1
  • There could be an issue in the kernel iptables code which allows for exploitation. If you are "lucky", that could allow someone to break in even with empty rulesets with all policies set to DROP.
    – user
    Commented Oct 31, 2015 at 15:21
0

You may want to restrict the ip ranges, from which you can reach ssh (and maybe openvpn). Make sure to add at least one range, where you know you will have access to even when your provider switches the subnet from which your ip comes. If you have another server, add its ip. You may even consider only allowing ssh from such an jump host.

0

The point is, you don't have perfect security, because a system is only as secure as its weakest component. If ssh and/or openvpn can be compromised, someone can hack his way into your server by those means, and if there's something wrong in the netfilter code, you could have packets slip through. Also, if openSSH and/or openVPN are using too weak encryption (various ciphers and hash algorithms are known to be weak), the connections can be attacked as well.

Also, your firewall setup is incomplete and in need of improvement. First of all, you don't have to set OUTPUT to DROP, because that spares you a lot of extra work (you don't have to add policies for outbound packets).

Then, I'd also do a complete overhaul of the firewall rules in general:

  • Ditch the -m state --state xxx matches in the rules handling SSH, because they are unnecessary (it's the same as if the rules accepted any associated packets directly, albeit a little slower because of the overhead incurred by the match).
  • Ditch the -m state --state xxx matches in the rules handling openVPN. Since UDP (a connectionless protocol) is used, the match won't even work.
  • If you want to retain the default DROP policy for OUTPUT, make sure to exempt the loopback device on the OUTPUT chain so that internal services are able to send packets. Otherwise their transmissions would be blocked as well.
  • Your FORWARD section needs improvement: You may have opened the way out for packets arriving via openVPN's tunnel, but the way back is still blocked. Furthermore, only tcp traffic is allowed back because of the -m state --state ESTABLISHED,RELATED match, but UDP won't be sent back across the tunnel.
  • If you want to access your server via openVPN, you need to add appropriate rules for handling that traffic.

Also, if you want to improve your security even more, rerig openSSH to use pubkey authentication (make sure to disable any authentication scheme requiring username/password) and set up iptables with an automated blacklist:

iptables -N SSH
iptables -N SSH_ABL

iptables -A SSH -m recent --name SSH_ABL --update --seconds 7200 -j DROP
iptables -A SSH -m recent --name SSH --rcheck --seconds 600 --hitcount 3 -j SSH_ABL
iptables -A SSH_ABL -m recent --name SSH_ABL --set -j LOG --log-level warning --log-prefix "ABL: +SSH: "
iptables -A SSH_ABL -j DROP
iptables -A SSH -m recent --name SSH --rcheck --seconds 10 -j LOG --log-level warning --log-prefix "SSH-RATE: "
iptables -A SSH -m recent --name SSH --update --seconds 10 -j REJECT --reject-with icmp-admin-prohibited
iptables -A SSH -m recent --name SSH_ABL --remove -j LOG --log-level warning --log-prefix "ABL: -SSH: "
iptables -A SSH -m recent --name SSH --set -j ACCEPT

iptables -A INPUT -p tcp -m conntrack --ctstate ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp --dport <ssh-port> -m conntrack --ctstate NEW -j SSH

–– Source unknown

Then make sure to not directly ACCEPT any NEW packets meant for SSH, but instead direct them to the SSH chain. This prevents brute-force attacks on SSH.

It's also a good idea to put the rule accepting packets of ESTABLISHED TCP connections early into the rule set so that it is reached quickly, and you don't lose too much time processing those packets. You then only have to insert rules for handling NEW TCP connections (they can be placed late in the chain, because they don't penalize you that much as they are only hit on the SYN packet of a TCP connection). Also make sure to get rid of the default DROP policy for the OUTPUT chain. That way your server is able to establish TCP connections to the Internet, e. g. for updates of its system.

What you'd also want to do is set rules to accept replies to UDP traffic initiated by the server (either generic or limited to specific ports):

iptables -A INPUT -p udp -m conntrack --ctdir REPLY -j ACCEPT

or

iptables -A INPUT -p udp --sport <portnum> -m conntrack --ctdir REPLY -j ACCEPT

This may be necessary for the Network Time Protocol (UDP port 123) and DNS (UDP port 53).

Your firewall rules should then look like these:

iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

iptables -N SSH
iptables -N SSH_ABL

iptables -A SSH -m recent --name SSH_ABL --update --seconds 7200 -j DROP
iptables -A SSH -m recent --name SSH --rcheck --seconds 600 --hitcount 3 -j SSH_ABL
iptables -A SSH_ABL -m recent --name SSH_ABL --set -j LOG --log-level warning --log-prefix "ABL: +SSH: "
iptables -A SSH_ABL -j DROP
iptables -A SSH -m recent --name SSH --rcheck --seconds 10 -j LOG --log-level warning --log-prefix "SSH-RATE: "
iptables -A SSH -m recent --name SSH --update --seconds 10 -j REJECT --reject-with icmp-admin-prohibited
iptables -A SSH -m recent --name SSH_ABL --remove -j LOG --log-level warning --log-prefix "ABL: -SSH: "
iptables -A SSH -m recent --name SSH --set -j ACCEPT

iptables -t raw -A PREROUTING -i lo -j CT --notrack
iptables -t raw -A OUTPUT -o lo -j CT --notrack

iptables -A INPUT -p tcp -m conntrack --ctstate INVALID -j DROP
iptables -A INPUT -p tcp -m tcp ! --tcp-flags SYN,ACK,FIN,RST SYN -m conntrack --ctstate NEW -j DROP
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -p tcp -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --dport 8888 -m conntrack --ctstate NEW -j SSH
iptables -A INPUT -p udp -m multiport --sports 53,123 -m conntrack --ctdir REPLY -j ACCEPT
iptables -A INPUT -i venet0 -p udp --dport 1194 -j ACCEPT
iptables -A INPUT -i venet0 -p icmp --icmp-type 3/4 -j ACCEPT
iptables -A INPUT -j REJECT --reject-with icmp-port-unreachable

iptables -A FORWARD -i venet0 -p tcp -m conntrack --ctstate INVALID -j DROP
iptables -A FORWARD -i venet0 -p tcp -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i venet0 -p icmp -m conntrack --ctdir REPLY -j ACCEPT
iptables -A FORWARD -i venet0 -p udp -m conntrack --ctdir REPLY -j ACCEPT
# Replace the tun device identifier with the tun device set up by your openVPN.
iptables -A FORWARD -i tun0 -s 10.8.0.0/24 -j ACCEPT
iptables -A FORWARD -j REJECT --reject-with icmp-net-unreachable

iptables -t nat -A POSTROUTING -o venet0 -s 69.147.244.199 -j ACCEPT
iptables -t nat -A POSTROUTING -o venet0 -j SNAT --to-source 69.147.244.199

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .