--- On Tue, 9/15/09, Michiel Brandenburg <apex@xepa...> wrote:
> Further more I would suggest opening up 22 from the net so
> you can access all the machines ( another port say 22022
> would help against them scans but I never bothered ).
I see no reason not to use port 22 directly, instead of substituting another port. Any scanner will eventually find the other port. It's better to hide it in the firewall with some sort of "port knocking" routine. Here's what I use (iptables-restore format):
-A ssh -m state --state RELATED,ESTABLISHED -j ACCEPT
-A ssh -m connlimit --connlimit-above 1 -j REJECT
-A ssh -m recent --rcheck --seconds 90 --name ssh4 --rsource -j ACCEPT
-A ssh -m recent --rcheck --name ssh4 --rsource -j REJECT
By "[INPUT]", I mean the INPUT chain or a chain that is a child of it. You must decide on the matching criteria for adding (and removing) from the recent list. The 3 rules may be on different chains as long as the parent chain is INPUT.
The ruleset "ssh" handles all connections to the SSH port (chained from the INPUT chain). First, it accepts anything already connected. It limits connections to 1 per IP. New connections are accepted ONLY when they arrive within 90 seconds of the IP address being added to the recent list "ssh4". The last rule protects older entries (outside the time window) on the recent IP address list from falling into my countermeasures (which may cause IP lockout and includes a TCP TARPIT) in case there was much network congestion. Don't use the "--rttl" part of recent -- I have found it problematic(%). If one has any static addresses, append rules to permit them (leave state ESTABLISHED as the first rule).
This way, anyone that hasn't previously done the necessary "thing" to get onto the "ssh4" recent list will not even see the port as open but will fall through and get the default action that occurs when nothing matches (usually, DROP, REJECT, or a countermeasure like TARPIT).
"Port knocking" is usually used to add IPs to the recent list. Criteria: I will reveal parts of mine:
1) To add, the packet must come in addressed to a particular IP address. My machine has MORE than one (it virtually hosts a /29). The address may be an address DIFFERENT than the one that SSH is listening to as long as it's on the same physical machine (same firewall). If you have only one address, they will obviously be the same, but if you have more than one, I suggest that they (the knocking destination address and the SSH listener) be different. SSH should NOT be listening to 0.0.0.0:22, but to a specific address' port 22, and the input firewall rule should also tie "-d" to that specific address.
2) To remove, the address should NOT be specified - so if one is port-scanning across addresses only a single port (or small range), if they hit your knocking port on address A (exposing SSH), then when they hit the same port on address B (or hit address A again within the time limit - I used 5 minutes above), it hides SSH again.
3) The knock need not be UDP or TCP ports. ICMP or other IP protocols could be used. (All examples I've seen of port knocking use TCP or UDP.) Some could even have two-tiered knocking (2 or more ports in sequence - and any break in the sequence closes ALL - forcing a start-over*). If one does use TCP or UDP, one will often add the adjacent ports (+/-1 of the knocking port) to the removal rules, so sequential port scans will be shut down practically as soon as they're opened.
4) Note that the knocking entries do NOT use "-j" as the rules are not meant to be terminal. This may allow the normal default action (including countermeasure rules) to fire. I protect the knocking method from countermeasures with other rules. This allows the knocking port to be an open port for another service! If you don't need that, then I suggest "-j DROP" as an alternative choice.
* - The example uses a single list. If one has a multi-layered knock, one will have a removal ruleset chain that removes the IP from ALL recent lists used in the chain.
% - It turns out that some programs will set a TTL other than the default TTL used by the machine they're running on. For example (from a Windows ME machine), a ping reports 17 hops, recent (on the destination machine) reports 13 hops (it really shows the count remaining), and traceroute reports 14. This is due to differences of when the TTL is decremented. There is also the issue that some programs might start with a TTL count other than the OS's default. Therefore, don't use "--rttl" unless you can guarentee consistent results.
This is alot better than simply taking a different port than 22 for SSH. One can still do that, but I find the reassignment unnecessary. It simply appears as another unused port when the knocking isn't active.
I call my recent list used for this "ssh4" because I also use IPv6 and call that AF's list "ssh6". The name doesn't matter as long as it's unique to this function. Note that the snippets I've included will work for ip6tables without modification (except for your choice of addresses).
NOTE: If there is a disclaimer or other legal boilerplate in the above
message, it is NULL AND VOID. You may ignore it.