#!/bin/bash
#################################################################################
#
# Disable external SSH by default; require a door-knocker on tcp/$KNOCK to gain access.
#
# The current time-limited ssh_knock list can be viewed at: /proc/net/ipt_recent/ssh_knock
#
ipt=/sbin/iptables
KNOCK=1234 ## The door-knocker port: pick a nice randomish port number here
SSHLOG="-m limit --limit 30/minute --limit-burst 20 -j LOG --log-prefix"
## ssh_add: move somebody temporarily to the ssh_knock list.
$ipt -N ssh_add
$ipt -A ssh_add -m recent --name ssh_knock --set $SSHLOG "ssh_add: " ## add to list
$ipt -A ssh_add -j DROP ## pretend we ignored it
## ssh_del: remove an IP from the ssh_knock list.
$ipt -N ssh_del
$ipt -A ssh_del -m recent --name ssh_knock --rsource --remove $SSHLOG "ssh_del: " ## remove from list
$ipt -A ssh_del -j RETURN ## return to caller
## ssh_accept: accept an incoming SSH connection.
$ipt -N ssh_accept
$ipt -A ssh_accept $SSHLOG "CONNECT(ssh): "
$ipt -A ssh_accept -m recent --name ssh_knock --rcheck -j ssh_del ## remove from list
$ipt -A ssh_accept -j ACCEPT ## allow this one connection attempt
## ssh_filter: restrict ssh access to only those hosts on the ssh_knock list, one attempt, 15 seconds max:
$ipt -N ssh_filter
$ipt -A ssh_filter -m recent --name ssh_knock --rcheck --seconds 15 ! --hitcount 1 -j ssh_accept
$ipt -A ssh_filter -m recent --name ssh_knock --rcheck -j ssh_del
$ipt -A ssh_filter -j DROP ## ignore it
$ipt -I INPUT -p tcp --syn --dport $KNOCK -j ssh_add
$ipt -I INPUT -p tcp --syn --dport 22 -j ssh_filter