LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Security (https://www.linuxquestions.org/questions/linux-security-4/)
-   -   iptables ssh auto blocking, centos 5.3 (upgrd to 5.5 krnl from updates) (https://www.linuxquestions.org/questions/linux-security-4/iptables-ssh-auto-blocking-centos-5-3-upgrd-to-5-5-krnl-from-updates-884868/)

tedeansiii 06-06-2011 03:39 PM

iptables ssh auto blocking, centos 5.3 (upgrd to 5.5 krnl from updates)
 
I have a fiberoptic broadband 20MB synchronous pipe at my home. Over summer at my place of employment its pretty much dead for 3 months so when I'm not busy I play around on my home server. I have my 20mb pipe going directly into my wrt54gl, from there I have a wired connection going to my server(Centos 5.3 recently upgraded to 5.5 through updates.) It serves as a file server(Samba, SSH). My wrt54gl handles natting port 22 to my server. I have my wireless AP setup to hand out leases from .2-.20 and my server has a static of .100. Dyndns.org handles my name resolution via their free account method. I have a Mac Pro, iMac, Macbook, and a Toshiba Laptop with 64bit 7 running off wireless along with our cell phones, and my XBOX 360 also is wired directly for the gaming speed. I use all of the computers around my home to access the samba shares via unc path for file sharing and or working on projects. I had originally planned to upgrade the wrt54gl with a cisco e3200 or an e3000 but unfortunately ive come to find out dyndns and the e lines of cisco wireless AP's dont work with dyndns and get banned. So I would have to install the daemon on my server and put it as a directly connected server to my WAN link and install a second ethernet card and pass traffic through my server for the rest of my home which I am not going to do. All of the previous sentence because it would update dyndns with a 192.168.x.x address since its not directly connected. I use a combination of putty.exe and vnc viewer to tunnel 5900 through port 22 to my server. So from anywhere I am at I can access my screen securely and then rdp or vnc to the desktop of my local LAN computers. This allows me to only have port 22 open. I've been looking at my ssh logs and noticed I have been getting hit alot with ssh scans. I want to implement an iptables firewall on my linux machine just for the purpose of further securing port 22. I dont necessarily need natting on the iptables firewall but all I need is ssh in and out, web in, and samba out to local ip's only. For SSH this is what I want. I want to allow SSH from any IP but if it tries to login more than 3 times in one minute I want to block that IP for a full minute before it can try 3 more attempts. I also would like log to a file but have been having issues getting that to work as well. That way when I review logs and I see that an ip tries three times and then waits a minute and tries three more, etc... I can permanently block that ip or range of ip's by adding it to the iptables script.

Here is my current iptables script and it doesnt seem to be working for me. Can someone help me with this. I have played with this and read for almost two weeks and still cannot get it to work correctly.

Code:

#!/bin/bash
# In order to use this iptables firewall script you
# must have iptables installed. You also must be using
# a 2.4.x series Kernel, with iptables suppport compiled
# into it, which is standard for most newer linux distributions.
#
# If you need help compiling iptables into your kernel, please
# see our kernel Compile/Upgrade Guide located at
# www.linuxhelp.net/guides/
#
# Once the script has been edited with all your relevant
# information (IP's Network Interfaces, etc..) simply
# make the script executable and run it as root.
#
# chmod 700 fw_rules.sh
# ./fw_rules.sh
#
# If you would like to see what rules are currently set, as
# root run iptables -L
#
# If you've messed up and need to bring down the firewall
# for whatever reason, run iptables -F
#
# If you would like to have the firewall automatically
# come up at boot time, add the path to the script to
# the bottom of your /etc/rc.d/rc.local file. For instance
# /root/bin/fw_rules.sh
#
# If you're not sure about something, check out the iptables
# man page by typing 'man iptables' (without the ''s) at the
# command prompt.
#
# This script is an enhanced/modified version of the
# iptables-script written by Davion
#
# If you have any questions, please come to us in #Linuxhelp.net
# on the DALnet IRC network. (www.linuxhelp.net/ircinfo.shtml)

# The location of the iptables binary on your system.
IPT="/sbin/iptables"

# The network interface you will be protecting. For ADSL/dialup users,
# ppp0 should be fine. If you are using a cable internet connection or
# are connected to a LAN, you will have to change this to "eth0".
#INT="ppp0"
INT="eth0"

# The following rules will clear out any existing firewall rules,
# and any chains that might have been created.
$IPT -F
$IPT -F INPUT
$IPT -F OUTPUT
$IPT -F FORWARD
$IPT -F -t mangle
$IPT -F -t nat
$IPT -X

# These will setup our policies.
$IPT -P INPUT DROP
$IPT -P OUTPUT ACCEPT
$IPT -P FORWARD ACCEPT

# The following line below enables IP forwarding and thus
# by extension, NAT. Turn this on if you're going to be doing NAT or IP masquerading.
echo 1 > /proc/sys/net/ipv4/ip_forward

# Source NAT everything heading out the $INT (external)
# interface to be the given IP. If you have a dynamic IP
# address or a DHCP IP that changes semi-regularly, comment out
# the first line and uncomment the second line.
#
# Remember to change the ip address below to your static ip.
#
#$IPT -t nat -A POSTROUTING -o $INT -j SNAT --to 192.168.8.100
$IPT -t nat -A POSTROUTING -o $INT -j MASQUERADE

# This rule protects your forwarding rule.
$IPT -A FORWARD -i $INT -m state --state NEW,INVALID -j DROP

# If you would like to forward specific ports to other machines
# on your home network, edit and uncomment the rules below. They are
# currently set up to forward port 25 & 53 (Mail & DNS) to 10.1.1.51.
# Anything incoming over your $INT through your gateway will
# be automatically redirected invisibly to port 25 & 53 on 10.1.1.51
# Mail Traffic
#$IPT -t nat -A PREROUTING -i $INT -p tcp --dport 25 -j DNAT --to 10.1.1.51:25
# DNS Traffic
#$IPT -t nat -A PREROUTING -i $INT -p tcp --dport 53 -j DNAT --to 10.1.1.51:53
#$IPT -t nat -A PREROUTING -i $INT -p udp --dport 53 -j DNAT --to 10.1.1.51:53
# SSH Traffic
$IPT -t nat -A PREROUTING -i $INT -p tcp --dport 22 -j DNAT --to 192.168.8.100
# VNC Traffic
$IPT -t nat -A PREROUTING -i $INT -p tcp --dport 5900 -j DNAT --to 192.168.8.100
$IPT -t nat -A PREROUTING -i $INT -p tcp --dport 5901 -j DNAT --to 192.168.8.100
# NetBios-Ns Name Service Traffic (Samba)
$IPT -t nat -A PREROUTING -i $INT -p tcp --dport 137 -j DNAT --to 192.168.8.100       
$IPT -t nat -A PREROUTING -i $INT -p udp --dport 137 -j DNAT --to 192.168.8.100       

# NetBios-Dgm Datagram Service Traffic (Samba)
$IPT -t nat -A PREROUTING -i $INT -p tcp --dport 138 -j DNAT --to 192.168.8.100       
$IPT -t nat -A PREROUTING -i $INT -p udp --dport 138 -j DNAT --to 192.168.8.100       

# NetBios-Ssn Session Service Traffic (Samba)
$IPT -t nat -A PREROUTING -i $INT -p tcp --dport 139 -j DNAT --to 192.168.8.100       
$IPT -t nat -A PREROUTING -i $INT -p udp --dport 139 -j DNAT --to 192.168.8.100       

# Microsoft-ds Domain Service Traffic (Samba)
$IPT -t nat -A PREROUTING -i $INT -p tcp --dport 445 -j DNAT --to 192.168.8.100       
$IPT -t nat -A PREROUTING -i $INT -p udp --dport 445 -j DNAT --to 192.168.8.100       

# These two redirect a block of ports, in both udp and tcp.
#$IPT -t nat -A PREROUTING -i $INT -p tcp --dport 2300:2400 -j DNAT --to 10.1.1.50
#$IPT -t nat -A PREROUTING -i $INT -p udp --dport 2300:2400 -j DNAT --to 10.1.1.50

# Now, our SSH_WHITELIST chain.
$IPT -N SSH_WHITELIST

# Now, our firewall chain. We use the limit commands to
# cap the rate at which it alerts to 15 log messages per minute.
$IPT -N firewall
$IPT -A firewall -m limit --limit 15/minute -j LOG --log-prefix Firewall:
$IPT -A firewall -j DROP

# Now our dropwall chain, for the final catchall filter.
$IPT -N dropwall
$IPT -A dropwall -m limit --limit 15/minute -j LOG --log-prefix Dropwall:
$IPT -A dropwall -j DROP

# Our "Hey, them's some bad tcp flags!" chain.
$IPT -N badflags
$IPT -A badflags -m limit --limit 15/minute -j LOG --log-prefix Badflags:
$IPT -A badflags -j DROP

# And our silent logging chain.
$IPT -N silent
$IPT -A silent -j DROP

# This rule will accept connections from local machines. If you have
# a home network, enter in the IP's of the machines on the
# network below.
$IPT -A INPUT -i lo -j ACCEPT
$IPT -A INPUT -s 192.168.8.0/24 -d 0/0 -p all -j ACCEPT
#$IPT -A INPUT -s 10.1.1.51 -d 0/0 -p all -j ACCEPT
#$IPT -A INPUT -s 10.1.1.52 -d 0/0 -p all -j ACCEPT

# Drop these nasty packets! These are all TCP flag
# combinations that should never, ever occur in the
# wild. All of these are illegal combinations that
# are used to attack a box in various ways, so we
# just drop them and log them here.
$IPT -A INPUT -p tcp --tcp-flags ALL FIN,URG,PSH -j badflags
$IPT -A INPUT -p tcp --tcp-flags ALL ALL -j badflags
$IPT -A INPUT -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j badflags
$IPT -A INPUT -p tcp --tcp-flags ALL NONE -j badflags
#$IPT -A INPUT -p tcp --tcp-flags ALL SYN,RST SYN,RST -j badflags        #Commented out because my box tells me SYN,RST are invalid commands
#$IPT -A INPUT -p tcp --tcp-flags ALL SYN,FIN SYN,FIN -j badflags        #Commented out because my box tells me SYN,FIN are invalid commands

#NOT SURE HERE I want pinging to return no response as if the box didn't exist
# Drop icmp, but only after letting certain types through.
$IPT -A INPUT -p icmp --icmp-type 0 -j ACCEPT 
$IPT -A INPUT -p icmp --icmp-type 3 -j ACCEPT
$IPT -A INPUT -p icmp --icmp-type 11 -j ACCEPT
$IPT -A INPUT -p icmp --icmp-type 8 -m limit --limit 1/second -j ACCEPT
$IPT -A INPUT -p icmp -j firewall

# If you would like to open up port 22 (SSH Access) to various IP's
# simply edit the IP's below and uncomment the line. If you wish to
# enable SSH access from anywhere, uncomment the second line only.
#$IPT -A INPUT -i $INT -s 10.1.1.1 -d 0/0 -p tcp --dport 22 -j ACCEPT
#$IPT -A INPUT -i $INT -s 0/0 -d 0/0 -p tcp --dport 22 -j ACCEPT
$IPT -A SSH_WHITELIST -s "my work IP without quotes" -m recent --remove --name SSH -j ACCEPT
$IPT -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
$IPT -A INPUT -p tcp --dport 22 -m state --state NEW -j SSH_WHITELIST
$IPT -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 --rttl --name SSH -j ULOG --ulog-prefix SSH_BRUTE_FORCE
$IPT -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 --rttl --name SSH -j DROP
#$IPT -A INPUT -s BAD_GUY_IP -j DROP

# Open Samba for Local Computers
$IPT -A INPUT -i $INT -s 0/0 -d 0/0 -p udp --dport 137:139 -j ACCEPT
$IPT -A INPUT -i $INT -s 0/0 -d 0/0 -p udp --dport 445 -j ACCEPT

# If you are running a web server, uncomment the next line to open
# up port 80 on your machine.
#$IPT -A INPUT -i $INT -s 0/0 -d 0/0 -p tcp --dport 80 -j ACCEPT

# Lets do some basic state-matching. This allows us
# to accept related and established connections, so
# client-side things like ftp work properly, for example.
$IPT -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

# Uncomment to drop port 137 netbiso packets silently.
# We don't like that netbios stuff, and it's way too
# spammy with windows machines on the network.
#$IPT -A INPUT -p udp --sport 137 --dport 137 -j silent

# Our final trap. Everything on INPUT goes to the dropwall
# so we don't get silent drops.
$IPT -A INPUT -j dropwall


rayfordj 06-06-2011 09:34 PM

Maybe something like this:
Code:

iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent \
    --name NEW_SSH_ATTEMPT --update --seconds 60 --hitcount 4 -j DROP

iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent \
    --name NEW_SSH_ATTEMPT --set -j ACCEPT

With the above you should be able to [attempt] NEW ssh connections from a given source up to 4 times before being DROPped for 60 seconds. While systemA has hit its limit and is being dropped, systemB should still be able to successfully start NEW ssh connections as long as no more than 4 NEW attempts are made within 60 seconds. Might need to play around with it to suit your needs, but it should hopefully get you on your way. Also, not sure you'll need any of the other SSH stuff, but might not be a bad idea to have a "whitelist" if you know your work IP(s).

:study:

rayfordj 06-07-2011 10:34 AM

If I understand correctly, you do not need routing/forwarding on your "server" as that is being handled by "wrt54gl".

Is this correct?:
Code:


        Internet
          |
        wrt54gl
          |
 --------------------------
  |          |        |
 server      xbox    more-devices

If so, you could easily eliminate the PRE/POST/FORWARD rules since "server" is not handling any of that.






Quote:

Originally Posted by tedeansiii (Post 4378144)
For SSH this is what I want. I want to allow SSH from any IP but if it tries to login more than 3 times in one minute I want to block that IP for a full minute before it can try 3 more attempts. I also would like log to a file but have been having issues getting that to work as well. That way when I review logs and I see that an ip tries three times and then waits a minute and tries three more, etc... I can permanently block that ip or range of ip's by adding it to the iptables script.

To expand on the above, if you are counting the three attempts as the single NEW connection such that
ssh -> server
username: USER
password: PASS1
password: PASS2
password: PASS3

you'll want to adjust ' --hitcount ' option.

To expand on my previous example with "work IP(s) whitelist" (where work public IP range is fictitious 123.456.12.0/28) and logging to syslog which should then get picked up by logwatch if you run that and review:
Code:

# whitelist known (?trusted?) network block
iptables -A INPUT -s 123.456.12.0/28 -p tcp --dport 22 \
    -m state --state NEW -j ACCEPT

# limit scanned brute-force/dictionary login attempts
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent \
    --name NEW_SSH_ATTEMPT --update --seconds 60 --hitcount 2    \
    -j LOG --log-prefix " NEW_SSH_ATTEMPT DROP "

iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent \
    --name NEW_SSH_ATTEMPT --update --seconds 60 --hitcount 2 -j DROP

iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent \
    --name NEW_SSH_ATTEMPT --set -j ACCEPT

In the block above, I have adjusted hitcount = 2 so that you may attempt to ssh twice (for a total of 6 possible password attempts) before being logged and then dropped for 60 seconds.

It should fail something like this...
client --> server
username: USER1
password: PASS1
password: PASS2
password: PASS3
disconnect
client --> server
username: USER2
password: PASS1
password: PASS2
password: PASS3
disconnect
client --> server
DROP for 60 seconds



Here's a stripped down example leveraging your provided script with comments removed that might handle what you need with minimal fuss (just change 123.456.12.0/28 or remote it):
Code:

#!/bin/bash
IPT="/sbin/iptables"
INT="eth0"
$IPT -F
$IPT -F INPUT
$IPT -F OUTPUT
$IPT -F FORWARD
$IPT -F -t mangle
$IPT -F -t nat
$IPT -X
$IPT -P INPUT DROP
$IPT -P OUTPUT ACCEPT
$IPT -P FORWARD ACCEPT
$IPT -N firewall
$IPT -A firewall -m limit --limit 15/minute -j LOG --log-prefix " Firewall: "
$IPT -A firewall -j DROP
$IPT -N dropwall
$IPT -A dropwall -m limit --limit 15/minute -j LOG --log-prefix " Dropwall: "
$IPT -A dropwall -j DROP
$IPT -N badflags
$IPT -A badflags -m limit --limit 15/minute -j LOG --log-prefix " Badflags: "
$IPT -A badflags -j DROP
$IPT -A INPUT -i lo -j ACCEPT
$IPT -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
$IPT -A INPUT -p tcp --tcp-flags ALL FIN,URG,PSH -j badflags
$IPT -A INPUT -p tcp --tcp-flags ALL ALL -j badflags
$IPT -A INPUT -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j badflags
$IPT -A INPUT -p tcp --tcp-flags ALL NONE -j badflags
$IPT -A INPUT -s 192.168.8.0/24 -d 0/0 -p all -j ACCEPT
$IPT -A INPUT -p icmp --icmp-type 0 -j ACCEPT 
$IPT -A INPUT -p icmp --icmp-type 3 -j ACCEPT
$IPT -A INPUT -p icmp --icmp-type 11 -j ACCEPT
$IPT -A INPUT -p icmp --icmp-type 8 -m limit --limit 1/second -j ACCEPT
$IPT -A INPUT -p icmp -j firewall
$IPT -A INPUT -s 192.168.8.0/24 -p tcp --dport 22 -m state --state NEW -j ACCEPT
$IPT -A INPUT -s 123.456.12.0/28 -p tcp --dport 22 -m state --state NEW -j ACCEPT
$IPT -A INPUT -p tcp --dport 22 -m state --state NEW -m recent \
    --name NEW_SSH_ATTEMPT --update --seconds 60 --hitcount 2 -j dropwall
$IPT -A INPUT -p tcp --dport 22 -m state --state NEW -m recent \
    --name NEW_SSH_ATTEMPT --set -j ACCEPT
$IPT -A INPUT -i $INT -s 0/0 -d 0/0 -p udp --dport 137:139 -j ACCEPT
$IPT -A INPUT -i $INT -s 0/0 -d 0/0 -p udp --dport 445 -j ACCEPT
$IPT -A INPUT -j dropwall

Entire script with original and additional comments without chain "flow" reordering should be available at http://pastebin.com/7XnAimHB


:study:

salasi 06-07-2011 11:39 AM

In all cases, before doing anything with ssh (there are a number of options, or combinations of options...you need not just to go with the first one that you think of, but have a look at an overview of the whole range), please read this:

http://la-samhna.de/library/brutessh.html


All times are GMT -5. The time now is 02:18 PM.