1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Enhancing Dropbear / SSH security

Discussion in 'Tomato Firmware' started by MarioT, Apr 9, 2007.

  1. MarioT

    MarioT LI Guru Member

    Would there be a way (even by manually editing the config files) to secure a bit more the SSH server on this firmware? I already added the SSH key authentication, but my router gets "brute force" password attacks almost everyday.

    Something as basic as: 5 failed passwords -> lock access for 30 minutes would be enought to dether this type of attack I think.

    Suggestion for a future release?
     
  2. Slimey

    Slimey Network Guru Member

    Maybe you could try putting the ssh server on a different port instead of the default.
     
  3. MarioT

    MarioT LI Guru Member

    Good idea...

    Unfortunately, while changing the port to 2222, I managed to lock myself out for accessing my router from the office. Seems they block outgoing traffic on non-standard ports.

    Until I find something else, I think it seems to be reasonnable that a 1024 RSA2 authorized private key should keep them busy for a while.
     
  4. The Abominable David

    The Abominable David LI Guru Member

    In the past, I've used port 443, the SSL port. If your office allows https traffic out, you can use this port for SSH traffic, too.
     
  5. ntest7

    ntest7 Network Guru Member

    You can add commands to the Firewall script to limit access to the external ssh port to a certain number of connections/time unit.

    You can also limit the connections to a specific IP address or range if you want to frustrate all those script-kiddies in foreign countries.

    - on the Administration-Admin Access page, do not enable remote access for ssh. We will do that manually with the iptables commands below.

    - add the following commands to the Administration-Scripts-Firewall.
    Change the extssh argument if you want to use a different, unused external port; 80 (http), 443 (https), 465 (smtps), 587 (submission) are all good candidates for not being blocked if you don't use those services.
    (I'll separate the lines so you can remove any line wrapping)

    # set this to your local router address
    me=192.168.1.1

    # set this to the external ssh port
    extssh=22

    iptables -t nat -I PREROUTING -p tcp -d $ip --dport $extssh -j DNAT --to $me:22

    iptables -A wanin -m state --state NEW,ESTABLISHED,RELATED -p TCP -d $me --dport 22 -m limit --limit 5/hour --limit-burst 5 -j ACCEPT
     
  6. MarioT

    MarioT LI Guru Member

    That's exactly what I was looking for...

    I did not expect to be able to be that specific by using firewall scripts. That shoud be enough to to lock them out after a few attempts. They probably won't wait for an hour before moving to the next target.

    Thanks
     
  7. jimmo04

    jimmo04 LI Guru Member

    Doesn't work for PPPoE (interface ppp0)?

    This doesn't work for me. I'm using a Buffalo WHR-HP-G54 with PPPoE.

    IP address of the router: 192.168.20.1

    This is what I have in the Firewall script.

    Code:
    iptables -t nat -I PREROUTING -p tcp -d $(nvram get wan_ipaddr) --dport 22 -j DNAT --to 192.168.20.1:22
    
    iptables -A wanin -m state --state NEW,ESTABLISHED,RELATED -p TCP -d 192.168.20.1 --dport 22 -m limit --limit 5/hour --limit-burst 5 -j ACCEPT
    
    Can someone help? Thanks!
     
  8. ntest7

    ntest7 Network Guru Member

    Not working how?

    Some notes:
    Make sure Administration->Admin Access SSH Daemon section:
    Enable at startup must be checked
    Remote Access must be unchecked
    Port must be 22

    Also, rather than "$(nvram get wan_ipaddr)" try using the built-in variable "$ip" (without the quotes) to automatically insert your WAN IP. Don't know if that will help, but worth a try.

    Code:
    iptables -t nat -I PREROUTING -p tcp -d $ip --dport 22 -j DNAT --to 192.168.20.1:22
     

    Attached Files:

  9. jimmo04

    jimmo04 LI Guru Member

    I confirm that the SSH "Remote Access" setting is disabled on the GUI. When I say not working, I mean that I can't connect _at all_ from the outside (other host on the Internet). However, connecting from the LAN/WLAN always works.

    Also, I initially tried with $ip and it didn't work so I thought hmmm maybe this variable is not defined because I couldn't see the variable definition so I switched to the nvram trick but it didn't help.

    Interestingly, when I enable the SSH "Remote Access" on the GUI, connecting works perfectly from the outside. Unfortunately SSH is not secured by the connection limit trick when I do this.

    Maybe it has to do with the PPPoE connection? Could it be because it's a different interface? Could it be because it's a Buffalo router?

    Thanks!
     
  10. MarioT

    MarioT LI Guru Member

    The $ip variable doesn't seem to work...

    I had to use the NVRAM GET function too...

    The above script, (once tweaked a bit to work) had one drawback for me: as soon as Brute force begin, all ssh connection is blocked.

    I recompiled a test version of Tomato 1.06, and by including the recent match extension, seems I'm able to block only the offending source IP with this Script:

    Code:
    WANIP=$(nvram get wan_ipaddr)
    iptables -t nat -A PREROUTING -p tcp -d $WANIP --dport 22 -j DNAT --to 192.168.1.1:22
    iptables -A INPUT -d 192.168.1.1 -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH_LIMIT --rsource
    iptables -A INPUT -d 192.168.1.1 -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 90 --hitcount 4 --name SSH_LIMIT --rsource -j DROP
    iptables -A INPUT -d 192.168.1.1 -p tcp --dport 22 -j ACCEPT
    
    I'll try to forward the needed modifications to the author if he thinks that it might be of interest in a future release. Let me just test the stability of the code for a few days before.
     
  11. ntest7

    ntest7 Network Guru Member

    I use this on both a buffalo and a Linksys, both with Tomato 1.06, and $ip is automatically set on each of these. So I don't think it's the router brand. I don't use PPPoE so maybe $ip isn't set with a PPPoE connection.

    Either way, the fix would be to use like MarioT suggested:

    WANIP=$(nvram get wan_ipaddr)
    Then insert $WANIP where needed in the iptables command.

    Hmm, I thought this would only block the offending IP and didn't realize it would block ALL ssh access. Maybe there is some other solution than recompiling Tomato.
     
  12. Clovenhoof

    Clovenhoof Addicted to LI Member

    Hello,

    I'm having an ADSL connection, with DHCP obtained IP addresses, and I assume that this script will work only until my IP is the same that it was when I ran your script first time.

    I guess the solution could be the usage of cron to update the WANIP regularly, but as I'm not a linux-expert, I don't know how exactly to do that.

    Could someone please advise?
     
  13. Clovenhoof

    Clovenhoof Addicted to LI Member

    OK, I've figured out the cron - WAN IP update thing, but ran into another issue with MarioT's script's 2nd iptables-command:

    # iptables -A INPUT -d 192.168.1.1 -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH_LIMIT --rsource
    iptables: No chain/target/match by that name

    I'm using Tomato 1.17.1385, iptables v1.3.7

    Any idea, what's wrong?
     
  14. fyellin

    fyellin LI Guru Member

    Just out of curiousity. In the Adanced/Firewall menu, have you turned off responding to ping? The level of random crud coming to my machine seems to go down when the script kiddies don't know if the machine is there in the first place.

    I realize that this doesn't solve your problem, but it may make it a little bit less of an irritation.
     
  15. Clovenhoof

    Clovenhoof Addicted to LI Member

    Turning off response to ping provides you insufficient defense, if, for example, you are using any torrent client. It is turned off in my router, but I still experience the efforts of bruteforce-attackers.
     
  16. fyellin

    fyellin LI Guru Member

    I wonder what I'm doing right? My external ssh port is set to something only slightly non-standard. Yet I haven't seen any recent sign of attempted breakins in the logs.
     
  17. Clovenhoof

    Clovenhoof Addicted to LI Member

    Probably that you have the chance to change the port to a non-standard one. I'm using the ssh connection from various networks, where the non standard ports are mostly blocked, so changing the ssh port from the default one probably would prevent me to reach my router. That is why I'm interested in the iptables-solution.
     
  18. MarioT

    MarioT LI Guru Member

    The missing link is that the "recent" iptables extension has to be compiled also in the firmware. I've modded 1.06 and 1.07 that way, but when 1.11 came out, I've integrated the script into Jon's firewall SSH rules so I don't have to use the custom scripts at all.

    Since then, I've sent him an archive of the small modifications I've done, but seems not enough people care about that feature to warrants its integration in a future release.

    I'm still running that v1.11, but I guess with enough time, v1.19 could be done too.
     
  19. Clovenhoof

    Clovenhoof Addicted to LI Member

    Thanks for the info.
    Can that extension be added to the firm without recompiling? So, if I would like to solve this issue using only custom scripts, is there a way?
     
  20. MarioT

    MarioT LI Guru Member

    As I don't have much time to patch and recompile the latest version (+ the fact that v1.11 has all the stability and features I need), I prefer to make available the "recipe" I used with v1.11.

    All its doing is adding the "recent" module to IPtables, and add a firewall rule when WAN SSH is enabled so that the 4th attempt under 90sec gets blocked.

    Please use responsibly ;-)
     

    Attached Files:

  21. Clovenhoof

    Clovenhoof Addicted to LI Member

    Thank you - I'll look into this.
     
  22. MarioT

    MarioT LI Guru Member

    "ipt_recent" module now in Tomato!

    Just as a follow-up for those still interested in being protected against SSH brute force attacks...

    Seems like Tomato "original" version 1.21 now comes compiled with the right iptables extension to run the rules needed. All it is missing is this in the scripts section:

    Init tab:
    Code:
    insmod ipt_recent
    Firewall tab:
    Code:
    WANIP=$(nvram get wan_ipaddr)
    iptables -t nat -A PREROUTING -p tcp -d $WANIP --dport 22 -j DNAT --to 192.168.1.1:22
    iptables -A INPUT -d 192.168.1.1 -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH_LIMIT --rsource
    iptables -A INPUT -d 192.168.1.1 -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 90 --hitcount 4 --name SSH_LIMIT --rsource -j DROP
    iptables -A INPUT -d 192.168.1.1 -p tcp --dport 22 -j ACCEPT
    Thanks Jon for adding this possibility for everyone!
     
  23. leepa

    leepa Addicted to LI Member

    Thanks MarioT for instructions :)

    However, it did not work on my router at first...
    It turned out that you need to disable remote access for SSH daemon in gui (Administration -> Admin Access).
    Why? Because if it is enabled and you add MarioT's entries to the scripts, the INPUT chain will look like this:

    Code:
    # iptables -L INPUT -n
    Chain INPUT (policy DROP)
    target     prot opt source               destination
    DROP       0    --  0.0.0.0/0            0.0.0.0/0           state INVALID
    ACCEPT     0    --  0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
    ACCEPT     0    --  0.0.0.0/0            0.0.0.0/0
    ACCEPT     0    --  0.0.0.0/0            0.0.0.0/0
    ACCEPT     tcp  --  0.0.0.0/0            192.168.1.1         tcp dpt:443
    [b]ACCEPT     tcp  --  0.0.0.0/0            192.168.1.1         tcp dpt:22[/b]
               tcp  --  0.0.0.0/0            192.168.1.1         tcp dpt:22 state NEW recent: SET name: SSH_LIMIT side: source
    DROP       tcp  --  0.0.0.0/0            192.168.1.1         tcp dpt:22 state NEW recent: UPDATE seconds: 90 hit_count: 4 name: SSH_LIMIT side: source
    [b]ACCEPT     tcp  --  0.0.0.0/0            192.168.1.1         tcp dpt:22[/b]
    
    Note two rules in bold. The first one accepts connections on port 22 (result of an option in gui) and is matched first - the "recent" rules are appended afterwards and not taken into account while checking the packets.

    So, either you need to disable the option in gui (which is actually re-enabled in Firewall script) or play with the rules in the script, so they are inserted at the beginning (but in the right order). I chose the former, which seemed easier :)

    Now the result of this ipt_recent module:
    Code:
    Aug 12 08:50:36  authpriv.info dropbear[3642]: Child connection from 88.80.222.148:39289
    Aug 12 08:50:37  authpriv.warn dropbear[3642]: login attempt for nonexistent user from 88.80.222.148:39289
    Aug 12 08:50:38  authpriv.info dropbear[3642]: exit before auth: Disconnect received
    Aug 12 08:50:38  authpriv.info dropbear[3643]: Child connection from 88.80.222.148:39551
    Aug 12 08:50:39  authpriv.warn dropbear[3643]: login attempt for nonexistent user from 88.80.222.148:39551
    Aug 12 08:50:40  authpriv.info dropbear[3643]: exit before auth: Disconnect received
    Aug 12 08:50:40  authpriv.info dropbear[3644]: Child connection from 88.80.222.148:39809
    Aug 12 08:50:42  authpriv.warn dropbear[3644]: login attempt for nonexistent user from 88.80.222.148:39809
    Aug 12 08:50:42  authpriv.info dropbear[3644]: exit before auth: Disconnect received
    Aug 12 08:51:34  syslog.info -- MARK --
    Aug 12 09:51:40  syslog.info -- MARK --
    Aug 12 10:51:40  syslog.info -- MARK --
    Aug 12 11:11:40  authpriv.info dropbear[3660]: Child connection from 119.30.125.75:41826
    Aug 12 11:11:43  authpriv.info dropbear[3660]: exit before auth (user 'root', 1 fails): Disconnect received
    Aug 12 11:11:43  authpriv.info dropbear[3661]: Child connection from 119.30.125.75:41941
    Aug 12 11:11:46  authpriv.info dropbear[3661]: exit before auth (user 'root', 1 fails): Disconnect received
    Aug 12 11:11:46  authpriv.info dropbear[3662]: Child connection from 119.30.125.75:42065
    Aug 12 11:11:49  authpriv.info dropbear[3662]: exit before auth (user 'root', 1 fails): Disconnect received
    Aug 12 11:51:40  syslog.info -- MARK --
    
    Only 3 attempts from signle IP. Earlier I had over 50 attempts in about 5 minutes from one IP. Thx again Jon and MarioT :)
     
  24. Clovenhoof

    Clovenhoof Addicted to LI Member

    Thanks MarioT for calling our attention to this improvement and sharing your iptables rules. I've just tried it - works like a breeze.
     
  25. mrap

    mrap Addicted to LI Member

    I spent a few hours playing with the MarioT script, but it just blocks all SSH access. :frown:

    My iptables -L -n output is exactly the same as leepa in post#23 too :(

    Any help would be appreciated.
    Thanks.
     
  26. nvtweak

    nvtweak LI Guru Member

    Have you tried upgrading to version 1.25? This feature to limit SSH connections is now in the user interface, under Administration.
     
  27. mrap

    mrap Addicted to LI Member

    Upgrading to 1.25

    I downloaded it, but am waiting for it to be moved out of "Experimental" status (I'm using the teddy_bear USB mod version).

    Would you happen to have a screenshot of what it looks like or a list of the options?

    Thanks!
     
  28. nvtweak

    nvtweak LI Guru Member

    Here's a picture.
     

    Attached Files:

  29. mrap

    mrap Addicted to LI Member

    Thanks! That looks pretty much like what I'd want to do! I wonder if it limits all connections or by IP . . . guess I'll find out once I install it ;)
     
  30. nvtweak

    nvtweak LI Guru Member

    You're welcome.

    It applies to all new SSH connections to the router itself.
     

Share This Page