Link to home
Start Free TrialLog in
Avatar of Mark
Mark

asked on

iptables hitcount does not appear to be working

I have the iptables configuration shown below. I want it to drop connection for 60 seconds if there are 10 invalid ssh attempts. That should be line 1 (iptables --line-numbers line) in the list below. I set this with:

-I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent \
        --update --seconds 60 --hitcount 10 -j DROP

But, it doesn't appear to work. The first entry in the DROP list: 189.211.0.0/16 made 94 attempts within 1 minute on one host and 334 attempts within minutes on another.

What is wrong with my iptables setup?
> iptables -t filter -n -L -v --line-numbers | head -20
Chain INPUT (policy DROP 144 packets, 37456 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1        0     0 DROP       tcp  --  eth0   *       0.0.0.0/0            0.0.0.0/0           tcp dpt:22 state NEW recent: UPDATE seconds: 60 hit_count: 10 name: DEFAULT side: source
2     6478 5041K ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
3        3   176 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0
4        3   180 DROP       all  --  *      *       189.211.0.0/16       0.0.0.0/0
5       22  3789 ACCEPT     all  --  eth1   *       0.0.0.0/0            0.0.0.0/0           state NEW
6        0     0 DROP       all  --  *      *       62.117.0.0/16        0.0.0.0/0
7        0     0 DROP       all  --  *      *       50.116.0.0/18        0.0.0.0/0
:
:
96       0     0 DROP       all  --  *      *       117.21.0.0/16        0.0.0.0/0
97       0     0 DROP       all  --  *      *       112.220.0.0/16       0.0.0.0/0
98       0     0 DROP       all  --  *      *       1.179.0.0/16         0.0.0.0/0
99      54  3232 ACCEPT     tcp  --  eth0   *       0.0.0.0/0            0.0.0.0/0           multiport dports 22,25,80,443,3389,10025,20028 state NEW

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1      383  327K ACCEPT     all  --  eth1   *       0.0.0.0/0            0.0.0.0/0

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1     4541  405K ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
2     1105 70362 ACCEPT     all  --  *      eth0    0.0.0.0/0            0.0.0.0/0           state NEW
3        3   176 ACCEPT     all  --  *      lo      0.0.0.0/0            0.0.0.0/0
4        2   656 ACCEPT     all  --  *      eth1    0.0.0.0/0            0.0.0.0/0           state NEW

Open in new window

Avatar of Member_2_6582184
Member_2_6582184
Flag of Germany image

Can you also post your rule set from iptables --list?

What puzzles me is your accept rule in iptables line #2 above.
Avatar of Mark
Mark

ASKER

> What puzzles me is your accept rule in iptables line #2 above.

I got that rule many moons ago. It should only always accept already established connections, not new connections, no? (note that that rule is now at line 9 in the listing below, probably because I've restarted the firewall and new DROPs have been added.)

> Can you also post your rule set from iptables --list?

Not sure how that differs from the list in the initial posting, but here goes. I've got 95 DROPs, most of which I will remove from the list:
$ iptables -n --list
Chain INPUT (policy DROP)
target     prot opt source               destination
DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22 state NEW recent: UPDATE seconds: 60 hit_count: 10 name: DEFAULT side: source
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
DROP       all  --  211.157.0.0/16       0.0.0.0/0
DROP       all  --  189.211.0.0/16       0.0.0.0/0
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           state NEW
DROP       all  --  62.117.0.0/16        0.0.0.0/0
DROP       all  --  50.116.0.0/18        0.0.0.0/0
DROP       all  --  146.0.0.0/16         0.0.0.0/0
:
:
DROP       all  --  117.21.0.0/16        0.0.0.0/0
DROP       all  --  112.220.0.0/16       0.0.0.0/0
DROP       all  --  1.179.0.0/16         0.0.0.0/0
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           multiport dports 22,25,80,443,3389,10025,20028 state NEW

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           state NEW
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           state NEW

Open in new window

Avatar of arnold
You keep cutting the info half way through.

Your drop lines 96-98 should be near the top .
Why force the packet to go through 95 rules to which it may match if you want to drop any packet from that source?

Also you are using an explicit allow at the end for any data coming in eth0.
An external interface should be limited to related/established
and then deny/drop any IP segments that .....
Then allow the ports you want.
implicit or explicit deny for everything else.
Avatar of Mark

ASKER

Arnold: > You keep cutting the info half way through.

If you mean between lines 7 and 96 in my initial posting, that's just a whole bunch of more DROP lines exactly the same as those above and below except for the IP. Didn't see any sense is cluttering up this question will a lot of redundant lines.

> Your drop lines 96-98 should be near the top .

Well, they are near the top, aren't they? The DROPs start at line 6 with a straggler at line 4 (probably because I am dynamically inserting using: iptables -t filter -I INPUT 4 -s ...). The only thing above these DROPs are the eth0 hitcount line (1), the ACCEPT ESTABLISH,RELATED line (2),  the lo ACCEPT ALL (3), and the eth0 ACCEPT ALL (5). This ordering is as I understood your suggestion in https://www.experts-exchange.com/questions/28389230/iptables-not-blocking-IP-wrong-specification.html?anchorAnswerId=39938060#a39938060

> Why force the packet to go through 95 rules to which it may match if you want to drop any packet from that source?

Not sure I understand your question. These rules are inserted by a script which monitors attempted breakins every minute. If it finds an attempt, it adds a DROP rule. These rules get aged out periodically so the list doesn't get infinitely log. I usually end up with about 120 by the end of the month.

> Also you are using an explicit allow at the end for any data coming in eth0.

Which line is that? I don't see it.

> An external interface should be limited to related/established

See line, 2.

> and then deny/drop any IP segments that ...

lines 4 - 98.

> Then allow the ports you want.

line 99. Seems line my rules are in exactly the order you are recommending.

Now, my hitcount rule is at line 1, so it should be processing that rule before anything else. So why is it not working?
Hello,

sorry, it did not occur to me to scroll right in your original post, so I could not see the options - thinking it was a general accept rule.

I have to admit I normally do not setup more sophisticated rules using plain iptables. But in your case I suggest using the limit module over the recent module, as that's what you are doing anyway (also, I think the recent module needs a --rsource list to work):. Please note, they are academical as I haven't actually tested them:

-I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m limit --limit 10/min -j DROP

Open in new window


Also, here is a suggestion to usesing hit count; using a separate chain to untangle it from your auto added rules:
iptables -N SSH
iptables -A INPUT -i eth0 -p tcp -m tcp --dport 22 -m state --state NEW -j SSH
iptables -A SSH -m recent --set --name SSHLIST --rsource
iptables -A SSH -m recent --update --seconds 60 --hitcount 10 --name SSHLIST --rsource -j DROP
iptables -A SSH -j ACCEPT

Open in new window

Any IP with a lower then 10 hit count in the list SSHLIST should be accepted. List is reset after 60 seconds.
Note: IMOH the seconds time in the recent module should be chosen longer to make sense; like 3600.
Consider adding a limiter such as

iptables -A INPUT -p tcp --syn -m limit --limit 5/s -i eth0 -dport 22 -j ACCEPT

You are forwarding all (allowing)

Iptables flow external connections first hit INPUT
They then go through FORWARD

It is simpler to control your setup so that you can see what is going on as well as not commingling packets from different interfaces.....

Create separate iptables chains.
One would explicitly only apply to your external interface which will be used in

iptables -N external_restrictions_rules
iptables -N internal_traffic_rules
Iptables -t filter -A INPUT -i eth0 -j external_restriction_rules
Iptables -t filter -A FORWARD -i eth0 -j external_restriction_rules
Iptables -t filter -A INPUT -i eth1 -j internal_traffic_rules
Iptables -t filter -A FORWARD -i eth1 -j internal_traffic_rules

Then distribute the rules to the appropriate chains. Because the interface is part of the earlier rule, you do not need to specify the interface in the rules being added into the chain.

Iptables -A external_restriction_rules

Another option is to use fwbuilder


The commingling and mixed entries with/without interface option could have an errand rule that matches and allows the traffic you want blocked through.

Eth0 is facing the outside/public IP.
Eth1 is using an internal private IP block?
Avatar of Mark

ASKER

sorry for the delay folks, end of quarter issues.

Clearly I have something configured wrong. I had 714 attempts by one attacker within one minute, even though I have the hitcount configured. Maybe my hitcount is configured wrong as Daniel Helgenberger suggested ( --rsource list?). Maybe I need the limiter that Arnold and Daniel Helgenberger mentioned.

However, I need a bit more description on things to understand. Is Arnold's suggested:

iptables -A INPUT -p tcp --syn -m limit --limit 5/s -i eth0 -dport 22 -j ACCEPT

in addition to or instead of my current ACCEPT (line 20, below)? I'm not particularly worried about DROPs applying to eth0 and eth1. eth1 is an internal LAN, no Internet connection.

I'll post my current config script so you can see where I am so far with suggestions. Meanwhile, I'll check out fwbuilder. I  don't hand-configure sendmail anymore (nor do I poke OP-codes into memory) and iptables is even more daunting than sendmail.
    iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

    iptables -A INPUT -i lo -j ACCEPT

    iptables -A INPUT -i eth1 -m state --state NEW -j ACCEPT

    # BLOCK THESE IPs FOR ATTEMPTED HACKING

/usr/sbin/iptables -t filter -I INPUT 4 -s 221.120.224.0/16 -j DROP
/usr/sbin/iptables -t filter -I INPUT 4 -s 117.27.158.0/16 -j DROP  
/usr/sbin/iptables -t filter -I INPUT 4 -s 206.212.243.0/16 -j DROP 
:
: (lots more of these)

    # The following blocks an IP for 60 seconds after 10 unsuccessful ssh attempts

    iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent \
        --update --seconds 60 --hitcount 10 -j DROP

    iptables -A INPUT -p TCP -i eth0 -m multiport \
        --dports 22,25,53,80,443 -m state --state NEW -j ACCEPT

    iptables -A INPUT -p UDP -i eth0 -m multiport --dports 53 -m state --state NEW -j ACCEPT

    iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

# Permit bu6500.ohprs.org to sync time with webserver

    iptables -I INPUT -p tcp -m tcp -s 64.129.23.99 --dport 37 -j ACCEPT -j ACCEPT

    iptables -A OUTPUT -o eth0 -m state --state NEW -j ACCEPT

    iptables -A OUTPUT -o lo -j ACCEPT

    iptables -A OUTPUT -o eth1 -m state --state NEW -j ACCEPT

Open in new window

Avatar of Mark

ASKER

I fear I may have lost my audience on this one. I'll post my latest config script and iptables -L and, if no response, I'll repost a fresh question.

I've incorporated the --limit suggestion, but still I am not getting attempts limited to 10. One recent example had 43 attempts in the first minute with another 47 attempts after the iptables command was run to block it.

So, something is wrong with either my syntax or rule order. I've not yet logged a "SSH Break-in attempt" message.

Also, I'm not going to try fwbuilder for various reasons including that it uses a GUI setup and I'm doing this mostly remotely via command shell.

Also, I haven't put things in chains because I really don't get what chains are! I understand the notion of INPUT and OUTPUT tables, ... but I don't get what a chain is other than a macro-like convention to avoid having to repeat settings. I haven't found a good concept description on the web.

Reminder: eth0 is Internet facing, eth1 is LAN facing.

    iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

    iptables -A INPUT -i lo -j ACCEPT

    iptables -A INPUT -i eth1 -m state --state NEW -j ACCEPT

iptables -t filter -I INPUT 4 -s 217.128.225.0/16 -j DROP   
iptables -t filter -I INPUT 4 -s 49.236.204.0/16 -j DROP   
iptables -t filter -I INPUT 4 -s 123.30.168.0/16 -j DROP   
iptables -t filter -I INPUT 4 -s 203.113.122.0/16 -j DROP  

    # The following blocks an IP for 60 seconds after 10 unsuccessful ssh attempts
    # https://we.riseup.net/debian/iptables-recent-module-and-hit-limits

    iptables -A INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent --update --seconds 60 \
        --hitcount 10 --rsource -j LOG --log-prefix "SSH Break-in attempt" --log-level 6

   iptables -A INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent --update --seconds 60 \
        --hitcount 10 --rsource -j DROP

   iptables -A INPUT -p TCP -i eth0 -m multiport --dports 22,25,53,80,443 -m state --state NEW -j ACCEPT

    iptables -A INPUT -p tcp --syn -m limit --limit 1/s -i eth0 --dport 22 -j ACCEPT

   iptables -A INPUT -p UDP -i eth0 -m multiport --dports 53 -m state --state NEW -j ACCEPT

    iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

# Permit bu6500.ohprs.org to sync time with webserver

    iptables -I INPUT -p tcp -m tcp -s 64.129.23.99 --dport 37 -j ACCEPT

# Permit all outgoing connections
#    $IPT -A OUTPUT -p TCP -o eth0 -m multiport \
#       --dports 22,25,37,43,53,80,20022,20028,2222,10021,6200:6220 -m state --state NEW -j ACCEPT

#    $IPT -A OUTPUT -p UDP -o eth0 -m multiport --dports 53 -m state --state NEW -j ACCEPT
    iptables -A OUTPUT -o eth0 -m state --state NEW -j ACCEPT

    iptables -A OUTPUT -o lo -j ACCEPT

   iptables -A OUTPUT -o eth1 -m state --state NEW -j ACCEPT

Open in new window


$ iptables -L -v -n
Chain INPUT (policy DROP 12523 packets, 2426K bytes)
 pkts bytes target     prot opt in     out     source               destination
    8   432 ACCEPT     tcp  --  *      *       64.129.23.99         0.0.0.0/0           tcp dpt:37
 402M  825G ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
 4365  262K ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0
    4   240 DROP       all  --  *      *       203.113.0.0/16       0.0.0.0/0
    0     0 DROP       all  --  *      *       123.30.0.0/16        0.0.0.0/0
    4   192 DROP       all  --  *      *       49.236.0.0/16        0.0.0.0/0
   15   720 DROP       all  --  *      *       217.128.0.0/16       0.0.0.0/0
30726 3525K ACCEPT     all  --  eth1   *       0.0.0.0/0            0.0.0.0/0           state NEW
    1    48 DROP       all  --  *      *       83.222.0.0/16        0.0.0.0/0
    2    96 DROP       all  --  *      *       122.224.0.0/16       0.0.0.0/0
    0     0 DROP       all  --  *      *       89.248.0.0/16        0.0.0.0/0
    0     0 DROP       all  --  *      *       211.157.0.0/16       0.0.0.0/0
   24  1152 DROP       all  --  *      *       118.97.0.0/16        0.0.0.0/0
    0     0 LOG        tcp  --  eth0   *       0.0.0.0/0            0.0.0.0/0           tcp dpt:22 state NEW recent: UPDATE seconds: 60 hit_count: 10 name: DEFAULT side: source LOG flags 0 level 6 prefix `SSH Break-in attempt'
    0     0 DROP       tcp  --  eth0   *       0.0.0.0/0            0.0.0.0/0           tcp dpt:22 state NEW recent: UPDATE seconds: 60 hit_count: 10 name: DEFAULT side: source
21867 1167K ACCEPT     tcp  --  eth0   *       0.0.0.0/0            0.0.0.0/0           multiport dports 22,25,53,80,443 state NEW
    0     0 ACCEPT     tcp  --  eth0   *       0.0.0.0/0            0.0.0.0/0           tcp dpt:22 flags:0x17/0x02 limit: avg 1/sec burst 5
   17  1129 ACCEPT     udp  --  eth0   *       0.0.0.0/0            0.0.0.0/0           multiport dports 53 state NEW

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
 247M  266G ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
13326  912K ACCEPT     all  --  *      eth0    0.0.0.0/0            0.0.0.0/0           state NEW
 4365  262K ACCEPT     all  --  *      lo      0.0.0.0/0            0.0.0.0/0
 111K 7427K ACCEPT     all  --  *      eth1    0.0.0.0/0            0.0.0.0/0           state NEW

Open in new window

INPUT OUTPUT PREROUTING POSTrouting are the builtin chains.
 your limit on port 22 is one line below the allow port 22 as part of multi port.

Try moving line 20 on the input above line 19.


The majority of your INPUT traffic hits on line 5.

Using chains as I suggested could help provide visibility which rule allows the traffic.  An option to use snort (search snort+iptables) that can be setup as an IPS/IDS
Avatar of Mark

ASKER

arnold: > Try moving line 20 on the input above line 19.

OK, I've done that. I'll get back with results. But why would the hitcount rules on lines 17 and 18 not be triggering? They are both above line 20.

> The majority of your INPUT traffic hits on line 5.

Yes, but that is for RELATED, ESTABLISHED connections, so would be OK, right? Or is that line superfluous?

As far as "rule visibility" goes, I have a cron script that runs each minute monitoring /etc/log/messages for "Invalid user" and "Failed passwords" attempts, as well as monitoring port 25 and (optionally) port 21. It counts failures over the life of the /etc/log/messages file. If a potential intruder is found, that script runs `iptables -t filter -I INPUT 4 -s <iprange> -j DROP`. This is not part of the basic firewall startup script (although the firewall script does source DROP rules created by the cron script). Periodically, all the DROPs are cleared out and starts from scratch. I'm only concerned about eth0 attempts, so I suppose I could limit the DROP entries to `iptables -t filter -I INPUT 4 -i eth0 -s <iprange> -j DROP`, right?
The visibility deals with distinguishing between responses and outgoing and coung back, but after considering the related would encompass FTP type services

Yes. The drop on line four should match and ......
Avatar of Mark

ASKER

Well, this is frustrating. This thing still isn't working. I did move line 20 as advised and restarted the firewall script. Nevertheless, about 3 hours later we had 353 ssh attempts within 30 seconds from 183.62.232.96 (China) at which time the cron script ran, detected the breakin and entered a DROP rule. We received another 32 attempts over the next 5 seconds after the new DROP rule before the attack was blocked (probably stuff still in the queue).

At the moment, I believe there must be something wrong with my firewall script and not with iptables, though I'm beginning to wonder. (iptables v1.4.10).

(reference iptables -L -v, below, all but one dynamic DROP removed for conciseness)

1) Why does the limit rule at line 11 not limit connection attempts to 1 per second?

2) Why does the hitcount rule at line 10 not DROP an IP after more than 10 attempts in one minute?

3) why does the hitcount rule at line 9 not log a "SSH Break-in attempt" message in syslog?

None of these rules seem to be working as advertised. Why?

iptables -L -v -n
Chain INPUT (policy DROP 6576 packets, 1603K bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     tcp  --  *      *       64.129.23.99         0.0.0.0/0           tcp dpt:37
  23M 1623M ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
  418 25080 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0
 4075  196K DROP       all  --  *      *       183.62.0.0/16        0.0.0.0/0
 2459  324K ACCEPT     all  --  eth1   *       0.0.0.0/0            0.0.0.0/0           state NEW
    0     0 LOG        tcp  --  eth0   *       0.0.0.0/0            0.0.0.0/0           tcp dpt:22 state NEW recent: UPDATE seconds: 60 hit_count: 10 name: DEFAULT side: source LOG flags 0 level 6 prefix `SSH Break-in attempt'
    0     0 DROP       tcp  --  eth0   *       0.0.0.0/0            0.0.0.0/0           tcp dpt:22 state NEW recent: UPDATE seconds: 60 hit_count: 10 name: DEFAULT side: source
   72  3800 ACCEPT     tcp  --  eth0   *       0.0.0.0/0            0.0.0.0/0           tcp dpt:22 flags:0x17/0x02 limit: avg 1/sec burst 5
 1272 68192 ACCEPT     tcp  --  eth0   *       0.0.0.0/0            0.0.0.0/0           multiport dports 22,25,53,80,443 state NEW
    1    70 ACCEPT     udp  --  eth0   *       0.0.0.0/0            0.0.0.0/0           multiport dports 53 state NEW

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy DROP 1 packets, 40 bytes)
 pkts bytes target     prot opt in     out     source               destination
9924K   62G ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
 1712  115K ACCEPT     all  --  *      eth0    0.0.0.0/0            0.0.0.0/0           state NEW
  418 25080 ACCEPT     all  --  *      lo      0.0.0.0/0            0.0.0.0/0
 9443  642K ACCEPT     all  --  *      eth1    0.0.0.0/0            0.0.0.0/0           state NEW

Open in new window

Can you post the iptables raw file

Which Linux as a router guide did you follow?
Avatar of Mark

ASKER

> Can you post the iptables raw file

Well, I thought I *was* posting the raw file. What do you mean? What is the "raw file"?

> Which Linux as a router guide did you follow?

Hmmm, not a particular guide. For the initial firewall setup I got information from http://www.linuxquestions.org/questions/linux-security-4/need-basic-iptables-solutions-691808/ back in 2008. In addition, I followed postings on EE: https://www.experts-exchange.com/questions/22083572/Linux-Firewall-howto.html?anchorAnswerId=18272570#a18272570 and https://www.experts-exchange.com/questions/28259918/linux-iptables-block-all-but-specified-ports.html?anchorAnswerId=39552461#a39552461

For "router" set up, I haven't done much other than configure the eth1 as "2nd gateway" when I set this host up as a LAN mail server. I followed  http://linlog.blogspot.com/2010/02/multiple-gateways-on-same-host.html which is also discussed in https://www.experts-exchange.com/questions/28084123/After-changing-gateway-ssh-stops-working.html

Do you suspect a routing issue?

Excluding the dynamic DROPs, my configuration is less than a dozen script lines. Is there nothing obviously wrong?
route
https://www.experts-exchange.com/questions/28084123/After-changing-gateway-ssh-stops-working.html
I do not think this is a routing issue.

 
There are two portions to your linux as a router.
iptables -t filter -L : this would apply to your inbound traffic from the outside and returning traffic
and
iptables -t nat -L : this would apply to your inbound traffic from the defined LAN interface

there are also DNAT and SNAT ... dealing with altering the source/destination IP as needed.

The raw data will show how you have the interfaces defined. Whether you have NATed the LAN interface ......

prerouting/postrouting, output. etc. goes from the LAN out
INPUT, FORWARD, output goes from the outside in.

There are other options but these are the general one.
Avatar of Mark

ASKER

OK, here you go, basic config w/o the dynamic DROPs:

$ iptables -t filter -L
Chain INPUT (policy DROP)
target     prot opt source               destination
ACCEPT     tcp  --  mail.courtscan.com   anywhere            tcp dpt:time
ACCEPT     all  --  anywhere             anywhere            state RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere            state NEW
LOG        tcp  --  anywhere             anywhere            tcp dpt:ssh state NEW recent: UPDATE seconds: 60 hit_count: 10 name: DEFAULT side: source LOG level info prefix `SSH Break-in attempt'
DROP       tcp  --  anywhere             anywhere            tcp dpt:ssh state NEW recent: UPDATE seconds: 60 hit_count: 10 name: DEFAULT side: source
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:ssh flags:FIN,SYN,RST,ACK/SYN limit: avg 1/sec burst 5
ACCEPT     tcp  --  anywhere             anywhere            multiport dports ssh,smtp,domain,http,https state NEW
ACCEPT     udp  --  anywhere             anywhere            multiport dports domain state NEW

Chain FORWARD (policy DROP)
target     prot opt source               destination

Chain OUTPUT (policy DROP)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere            state RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere            state NEW
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere            state NEW

Open in new window


$ iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination

Open in new window

The issue deals whether you have PREROUTING defined to masquerade traffic from the LAN side interface.
On the NAT chain.

I still think defining and using separate chains within the builtin ones will help isolate where the traffic is coming from since you will be able to look at the statistics based on the chains rather than looking at a barrel that has both types of data.
I.e. The established,related will only apply to the chain that is common to the going out traffic.
The other issue, I have to recheck, whether your default policy on the filter side being drop, reverses the behavior.

Accept, means there is an implicit deny, the default drop policy, has an implicit accept when rules are not matched.

Editing so can not see prior.  Add an explicit drop to the end of the INPUT chain.
Rechecked myself, the Accept policy requires an explicit DROP at the end of the thread.


Search for Linux iptables as router.

There are examples. while many use iptables, the access/management of them differs.

As to your detection/addition process,
you would likely need to change it from the -A INPUT  which adds it at the bottom, to have it use -I INPUT x where x is the line on which your allow/accept rule is.
i.e. in the most recent info,

While writing the above, I see you do not have any FORWARD rules defined.

Where are you seeing the ssh access attempts on the system that you are using as a router?
INPUT only allows traffic into the firewall chain, you do not have a rule that --to-destination LAN_IP:port which is a port forward setup
You have allow, but I do not see where the multiport rules are supposed to be directed.
Avatar of Mark

ASKER

> Where are you seeing the ssh access attempts on the system that you are using as a router?

In /etc/log/messages, e.g.:

Apr  9 18:06:04 webserver sshd[25593]: Failed password for invalid user root from 183.62.232.96 port 54006 ssh2

> As to your detection/addition process,
> you would likely need to change it from the -A INPUT  which adds it at the bottom, to
> have it use -I INPUT x where x is the line on which your allow/accept rule is.

Yes, I've already done that. See your response to https://www.experts-exchange.com/questions/28389230/iptables-not-blocking-IP-wrong-specification.html?anchorAnswerId=39932087#a39932087, where x is 4.

Regarding your other commentary ... Wow! you've totally lost me! Accept/excplict DROP? Why do I need FORWARD rules? ...

My script has 13 explicit iptables commands to set rules, not that many. At this point you should have a pretty good idea what I'm after. How about if you reorg/revise these commands and show me how it should be to accomplish what I want. I'll implement that. Then I can reverse engineer and understand what your doing. That might take you a whole lot less byte-space than all the typing you've been doing.

My script:
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -i eth1 -m state --state NEW -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent --update --seconds 60 \
        --hitcount 10 --rsource -j LOG --log-prefix "SSH Break-in attempt" --log-level 6

iptables -A INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent --update --seconds 60 \
        --hitcount 10 --rsource -j DROP

iptables -A INPUT -p tcp --syn -m limit --limit 1/s -i eth0 --dport 22 -j ACCEPT
iptables -A INPUT -p TCP -i eth0 -m multiport --dports 22,25,53,80,443 -m state --state NEW -j ACCEPT
iptables -A INPUT -p UDP -i eth0 -m multiport --dports 53 -m state --state NEW -j ACCEPT
iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -I INPUT -p tcp -m tcp -s 64.129.23.99 --dport 37 -j ACCEPT
# Permit all outgoing connections
iptables -A OUTPUT -o eth0 -m state --state NEW -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A OUTPUT -o eth1 -m state --state NEW -j ACCEPT

Open in new window


btw, the script also does the following by way of initialization when starting and before doing the above ... if this makes any difference:

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

    iptables -t nat -P PREROUTING ACCEPT
    iptables -t nat -P POSTROUTING ACCEPT
    iptables -t nat -P OUTPUT ACCEPT

    iptables -t mangle -P PREROUTING ACCEPT
    iptables -t mangle -P INPUT ACCEPT
    iptables -t mangle -P FORWARD ACCEPT
    iptables -t mangle -P OUTPUT ACCEPT
    iptables -t mangle -P POSTROUTING ACCEPT

    iptables -t raw -P PREROUTING ACCEPT
    iptables -t raw -P OUTPUT ACCEPT

    iptables -F
    iptables -F -t nat
    iptables -F -t mangle
    iptables -F -t raw

    iptables -X
    iptables -X -t nat
    iptables -X -t mangle
    iptables -X -t raw

Open in new window

Is this system used as a router/firewall.
There is a confusion in your approach.
Incoming into your WAN side network interface
-t filter Deals with incoming traffic and diversions.
Hits input, goes out of output forward is used for port forwarding/diversions.


-t NAT is you LAN portion.


Your mangle rules are likely where the diversions occur.

If your LAN has 192.168.0.0/24 IP range is ssh! https and all other servers located on systems with that range.

                           ( Linux server )
Internet <=> ( filter  <=|=> nat ) <=> LAN
Avatar of Mark

ASKER

> Is this system used as a router/firewall.

OK, I think I see the point of confusion. Yes, this host has a firewall ... to this host only! No, it is not used as a router for the LAN.

There are two public IP in this network: 64.129.23.this and 64.129.23.that.

Public IP 64.129.23.that routes to a MicroTik firewall/router that is the 192.168.0.1 gateway and is the router for the 192.168.0.0/24 LAN. On that LAN is a SBS2008 server at 192.168.0.2 which is the LAN DNS and DHCP server for all hosts.

Public IP 64.129.23.this routes to this Linux box on eth0. This host has a 2nd NIC at 192.168.0.3 on eth1 which makes it a member of the LAN. This Linux host at 192.168.0.3 does not do routing or firewalling for the LAN. My firewall concerns here are purely local to this host.

Therefore, I don't care what happens on eth1 -- that's the MicroTik's problem. Only local LAN workstations are going to be talking on eth1. I just want to make sure that LAN hosts can get to the Linux host, and visa-versa, for e.g. samba mounts, SQL Server connections, etc. So I've basically allowed everything on eth1.

The Linux host accepts outside connections on port 22,25,53,80, and 443 on eth0. I'm just trying to trap abuses on those ports on that interface only. Concerning this current question, specifically for port 22. That's it.

Does that clarify things? Simplify?

What I want:

1) restrict port 22 connection attempts to 1 per second on eth0.

2) drop/block IP for one minute if more than 10 failed port 22 connection attempts on eth0.

3) Log to syslog if more than 10 failed port 22 connection attempts in one minute on eth0(not critical to do)

Everything else appears to work OK. Even if all I could accomplish would be #1, that would be good enough!!!!
I think your answer makes it more complicated.
Why are you using mangle to accept input, output traffic?

Do you have your microtik router/firewall configured to forward port 22 traffic to this system, 192.168.0.3?  That is likely the source of the attempts that you can not block.
I.e. You have attempts on both one directly, and one forwarded.
Avatar of Mark

ASKER

> Why are you using mangle to accept input, output traffic?

I just monkey-typed that from the response given to me in http://www.linuxquestions.org/questions/linux-security-4/need-basic-iptables-solutions-691808/ as a firewall initialization step. I have no clue what "mangle" does. If you think that's causing problems I can remove lines 9-13, 20 and 25 as shown in my post ID: 39993368, second "code" listing. Please advise.

> Do you have your microtik router/firewall configured to forward port 22 traffic to this system,

No, microtik only forwards 25 to this system. Microtik blocks 22 -- does not forward it anywhere. 22 really only comes into 192.168.0.3 from eth0, but I (and only I) can log in from a LAN workstation via eth0 using putty, which I rarely do.
Lets try it this way.

You have two public IPs 64.129.23.this and 64.129.23.that
64.129.23.this <=> Mirotik <=> 192.168.0.3 (eth1)
                                                     Linux Box
64.129.23.that <=>     eth0       /


Try to consider whether you want to use new chains.
-N LAN_traffic -P Accept
-N WAN_traffic -P DROP

iptables -I INPUT 2 -i eth0 -j WAN_traffic
iptables -I OUTPUT -i eth0 -j WAN_traffic
iptables -I WAN_traffic 1 -m state established, related -j ACCEPT
iptables -I WAN_traffic 2 -m multiport 25,53,80,443 --m state --state new -j ACCEPT
iptables -I WAN_traffic 3 -p tcp --dport 22-m state --state NEW -m recent --update --seconds 60 \
        --hitcount 10 --rsource -j LOG --log-prefix "SSH Break-in attempt" --log-level 6
iptables -I WAN_traffic 4 -p tcp --dport 22 -m state --state NEW -m limit --limit 10/min -j DROP

add the applicable rules for LAN_traffic chain that you want.
you can then create your blocker chain in a similar manner such that your script can simply add entries to this filter_special chain that has to be above almost every rule.
To avoid your script mistakenly locking you out, you might want to make sure to have a rule for your specific external IP (if static)


Try the following, without making changes to your existing setup, add the new chains. and add the rules within.  Then position these new chains above the rules you already have to see whether they will match and make the adjustments that you want.
as long as you do not write (save the iptables changes)  reverting to what you have is a piece of cake.

At this point, it is necessary to see where these port 22 requests are coming from to make sure that they are not coming through the microtik and hitting LAN side eth1 of your linux system. Port forwarding will still reflect the original IP as the source for the request.
your iptables need to have/use marks to make sure requests coming in from the outside directly to eth0 have the requests sent out via eth0 as well. Similarly with eth1.
Only secure (443, 995, 993, 465, etc.) traffic can not vary i.e. a request sent to x.x.x.x will only accept a response from x.x.x.x anything else and a mismatch will be detected and the connection/negotiations fail.
Avatar of Mark

ASKER

Sorry for the delay, again, pressing matters elsewhere

OK, I will give your suggestion a shot. I think it's not too risky to just temporarily replace my current iptables config with something new. I'll keep the old script and will put it back in if something bad happens. Having a clean config will keep [my] confusion down. Here's what I'll try:
# Possible stripped-down initialization? If I shouldn't bother with this, let me know.

    iptables -P INPUT ACCEPT
    iptables -P FORWARD ACCEPT
    iptables -P OUTPUT ACCEPT
    iptables -t nat -F
    iptables -t mangle -F
    iptables -F
    iptables -X

# Your suggested chains

iptables -N LAN_traffic -P Accept
iptables -N WAN_traffic -P DROP

iptables -I INPUT 2 -i eth0 -j WAN_traffic
iptables -I OUTPUT -i eth0 -j WAN_traffic
iptables -I WAN_traffic 1 -m state established, related -j ACCEPT
iptables -I WAN_traffic 2 -m multiport 25,53,80,443 --m state --state new -j ACCEPT
iptables -I WAN_traffic 3 -p tcp --dport 22-m state --state NEW -m recent --update --seconds 60 \
        --hitcount 10 --rsource -j LOG --log-prefix "SSH Break-in attempt" --log-level 6
iptables -I WAN_traffic 4 -p tcp --dport 22 -m state --state NEW -m limit --limit 10/min -j DROP

Open in new window


Is that it? I notice that you don't have my UDP for port 53, but I can get started without that. RSVP, I'll wait for your thumbs-up before trying this.
try it, You need an accept rule for port 22 often there is a logaccept chain one creates, one line creates the log entry while the other accepts the connection.

Try it your way to see whether it will lock your output out.
Note that what you have is only limited to the incoming portion.
Avatar of Mark

ASKER

I'm not getting past the first command:

$ iptables -N LAN_traffic -P Accept
iptables v1.4.10: Cannot use -X with -Z

Not sure what that means. I don't see a use of -X or -Z in that command. It didn't make much sense trying the commands that add to that chain if I can't create the chain.

Do you have an idea what is wrong? I'll try to research creating a chain.
Line nine of your new script has iptables -X
Entry.

Can you post your current iptables script?
Avatar of Mark

ASKER

> Line nine of your new script has iptables -X

Actually, I didn't run that. I just typed `iptables -N LAN_traffic -P Accept` by hand on the command line.

I googled a few examples of creating a chain and none of the examples I've seen use the -P option with -N. Maybe it has to be done in 2 steps? :

iptables -N LAN_traffic
iptables -P LAN_traffic ACCEPT

Although the man page says, "Only built-in (non-user-defined) chains can have policies, and neither built-in nor user-defined chains can be policy targets."

Current attempted script:
iptables -N LAN_traffic -P Accept
iptables -N WAN_traffic -P DROP

iptables -I INPUT 2 -i eth0 -j WAN_traffic
iptables -I OUTPUT -i eth0 -j WAN_traffic
iptables -I WAN_traffic 1 -m state established,related -j ACCEPT
iptables -I WAN_traffic 2 -m multiport 25,53,80,443 --m state --state new -j ACCEPT
iptables -I WAN_traffic 3 -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 \
     --hitcount 10 --rsource -j LOG --log-prefix "SSH Break-in attempt" --log-level 6
iptables -I WAN_traffic 4 -p tcp --dport 22 -m state --state NEW -m limit --limit 10

Open in new window

Avatar of Mark

ASKER

In fact, I tried the 2-step thing and it didn't allow the -P:

$ iptables -N LAN_traffic
$ iptables -P LAN_traffic ACCEPT
iptables: Bad built-in chain name.
You are setting the default policy on the builtin INPUT, FORWARD, OUTPUT
The chain you create only has the rules you want.

My mistake in suggesting the setting of a default policy on a user created chain.
Avatar of Mark

ASKER

I don't think creating chains is going to help much anyway. These rules aren't that complex and should work with or without chains. I can see no reason I don't get log messages or limits. Maybe it's a problem with my version of iptables. What do you think about closing this question and reposting the simplified current script and possibly getting some fresh eyes on the issue? I don't know where else we can go from here.
ASKER CERTIFIED SOLUTION
Avatar of arnold
arnold
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Mark

ASKER

yes, I know the disposition of the question is up to me. I'm soliciting your advice, not to mention consideration for your longsuffering participation and your continued enthusiasm.

I'm having difficulty grasping how chains will help solve the problem. I've not used chains before; your suggested setup didn't work and I don't know enough to correct the syntax. I can create the chains without the -P option, but not sure how to set the default policies after that.

As to "tracking the source", I'm not sure where you're going with that. The source is eth0, port 22. The up-stream firewall on eth1 does not permit port 22 and routes nothing but port 25 to this host. You can try it yourself. The up-stream firewall is at 64.129.23.80
The default policy is set on the built in chains as you have them now.

I.e
-P Input deny
Input 1 -i eth0 -J WAN_CHAIN

-P Input accept
Input 1 -i eth0 -j WAN_chain
Input 2 -j DROP

Your issue is unresolved. If comments here helped you in any way, choose the comments when closing the case and assign points as you think appropriate.

I can not suggest to you which comments are helpful to your situation.
Try
iptables -N LAN_traffic -P Accept
iptables -N WAN_traffic -P DROP

iptables -I INPUT 2 -i eth0 -j WAN_traffic
iptables -I OUTPUT -i eth0 -j WAN_traffic
iptables -I WAN_traffic 1 -m state established,related -j ACCEPT
iptables -I WAN_traffic 2 -m multiport 25,53,80,443 --m state --state new -j ACCEPT
iptables -I WAN_traffic 3 -p tcp --dport 22 -m state --state NEW -m recent --set -name SSH
iptables -I WAN_traffic 3 -p tcp --dport 22 -m state -m recent --state NEW --name SSH --update --seconds 60 \
     --hitcount 10 --rsource -j LOG --log-prefix "SSH Break-in attempt" --log-level 6
iptables -I WAN_traffic 3 -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 10 --hitcount 10 --name SSH -j DROP
iptables -I WAN_traffic 4 -p tcp --dport 22 -m state --state NEW -m limit --limit 10 -j DROP

Open in new window

Avatar of Mark

ASKER

Arnold - I appreciate all your time and effort, but I am no closer to solving this. It would have been very helpful if you could have posted an actual example that worked -- your recent examples had syntax errors on the very first rule and you posted no correction -- but perhaps you don't have a system handy to test your rules with.