Recently I had been looking for a solution to the problem where I would like to grant access to users to an SSH server which is externally available on the Internet, but add sensible firewall rules to protect the service.
I have hardened the SSH server and I am allowing my IP address to get to port 22, however when a user has a dynamic IP address, it makes it very difficult to write a firewall rule.
Relying on DNS for a firewall rule wasn't a great solution as many IPs may come from the same ISP I'd like to block (or allow), not to mention DNS can be spoofed.
There are many solutions to this problem, but fwknop is a very interesting one.
The author states:
"fwknop stands for the "FireWall KNock OPerator", and implements an authorization scheme called Single Packet Authorization (SPA). This method of authorization is based around a default-drop packet filter (fwknop supports both iptables on Linux systems and ipfw on FreeBSD and Mac OS X systems) and libpcap"
fwknop basically allows a user to set up a dynamic firewall rule after they have been authenticated.
Here's how it works
First, set your iptables ruleset such that all packets are dropped on port 22 (DENY).
Next, you install the fwknop server package on an SSH server you would like to protect and install the fwknop client on a client machine that wishes to connect.
The actual installation and configuration of the server didn't take me more than 15 minutes or so. The documentation is great.
When I ran the client it prompted me for my passphrase:

fwknop sent a single UDP packet to the server which was then consumed, decrypted the contents of the packet, confirmed my passphrase and then opened up a firewall rule for my IP address for 30 seconds as you see here in /var/log/messages:
Aug 7 15:03:49 Myhost fwknopd: received valid Rijndael encrypted packet from: 127.0.0.1 , remote user: j, client version: 1.9.11 (SOURCE line num: 26)
Aug 7 15:03:50 Myhost fwknopd: add FWKNOP_INPUT 127.0.0.1 -> 0.0.0.0/0(tcp/22) ACCEPT rule 30 sec
Note the new rule referencing the FWKNOP_INPUT chain now:
#iptables -L -n
Chain INPUT (policy DROP)
target prot opt source destination
FWKNOP_INPUT all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
BLACKLIST all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:443
Chain FWKNOP_INPUT (1 references)
target prot opt source destination
ACCEPT tcp -- 127.0.0.1 0.0.0.0/0 tcp dpt:22
The rule expired after 30 seconds:
Aug 7 15:03:50 Myhost fwknopd: add FWKNOP_INPUT 127.0.0.1 -> 0.0.0.0/0(tcp/22) ACCEPT rule 30 sec
Aug 7 15:04:21 Myhost fwknop(knoptm): removed iptables FWKNOP_INPUT ACCEPT rule for 127.0.0.1 -> 0.0.0.0/0(tcp/22), 30 sec timeout exceeded
That's a crude and quick story, but what's great about this is that I can deny all IP addresses on the Internet for SSH access and not worry about any particular scripts that are run against the server.
Before a user can even attempt to validate their username and password (or public key,etc) they need to authenticate with this fwknop server.
This severely reduces the possibility of an attack, because at this point you have only about 30 seconds to exploit the server.
I highly recommend this if this suits your environment.



0 comments:
Post a Comment