Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
##############################################################################
##
## iptables rules for a Tor node with port knocking hiding SSH.
##
## These rules are based on a combination of:
## https://raw.githubusercontent.com/torservers/
## server-config-templates/master/iptables.test.rules
## and
## https://www.debian-administration.org/article/
## 268/Multiple-port_knocking_Netfilter/IPtables_only_implementation
##
## For further info see:
## https://balist.es/blog/2016/05/03/configure-port-knocking-for-a-tor-node
##
## Some parameters you may want to change:
## * Ports on which to knock:
## 1. KNOCK1: 23456
## 2. KNOCK2: 34567
## 3. KNOCK3: 45678
## 4. KNOCK4: 56789
## * SSH port: 4992
## * Tor ports:
## * DirPort: 80
## * DirPort: 443
##
##############################################################################
*raw
-A PREROUTING -j NOTRACK
-A OUTPUT -j NOTRACK
COMMIT
*filter
## Set default rules and reset packet and byte counts
## See: https://www.krenger.ch/blog/iptables-accept-00-brackets/
:INPUT ACCEPT [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
## Allows all loopback (lo0) traffic and drop all traffic to 127/8 that
## doesn't use lo0
-A INPUT -i lo -j ACCEPT
## allow incoming SSH for testing:
# -A INPUT -p tcp --dport 2222 -j ACCEPT
## DirPort, ORPort (optional: Webserver)
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT
## Allow several ICMP types
## http://www.oregontechsupport.com/articles/icmp.txt
-A INPUT -p icmp -m icmp --icmp-type host-unreachable -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type port-unreachable -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type fragmentation-needed -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type source-quench -j ACCEPT
-A INPUT -p icmp --icmp-type echo-request -m limit --limit 2/s -j ACCEPT
-A INPUT -p icmp --icmp-type echo-request -j DROP
-A INPUT -p icmp -j DROP
## Define port knocking
-N INTO-PHASE2
-A INTO-PHASE2 -m recent --name PHASE1 --remove
-A INTO-PHASE2 -m recent --name PHASE2 --set
-A INTO-PHASE2 -j LOG --log-prefix "INTO PHASE2: "
-A INTO-PHASE2 -j DROP
-N INTO-PHASE3
-A INTO-PHASE3 -m recent --name PHASE2 --remove
-A INTO-PHASE3 -m recent --name PHASE3 --set
-A INTO-PHASE3 -j LOG --log-prefix "INTO PHASE3: "
-A INTO-PHASE3 -j DROP
-N INTO-PHASE4
-A INTO-PHASE4 -m recent --name PHASE3 --remove
-A INTO-PHASE4 -m recent --name PHASE4 --set
-A INTO-PHASE4 -j LOG --log-prefix "INTO PHASE4: "
-A INTO-PHASE4 -m recent --rcheck --name PHASE4 -j LOG --log-prefix "(OPEN PORT 4992) - "
-A INTO-PHASE4 -j DROP
## if you want to kock using tcp packets uncomment this line:
# -A INPUT -m recent --update --name PHASE1
## Define knocking sequence: knock on ports and then open SSH port for 5 seconds
-A INPUT -p udp --dport 23456 -m recent --set --name PHASE1
-A INPUT -p udp --dport 34567 -m recent --rcheck --name PHASE1 -j INTO-PHASE2
-A INPUT -p udp --dport 45678 -m recent --rcheck --name PHASE2 -j INTO-PHASE3
-A INPUT -p udp --dport 56789 -m recent --rcheck --name PHASE3 -j INTO-PHASE4
-A INPUT -p tcp --dport 4992 -i eth0 -m recent --rcheck --seconds 5 --name PHASE4 -j ACCEPT
## drop non-established TCP
-A INPUT -p tcp --syn -j DROP
## reject connections on port 4992
-A INPUT -p tcp --dport 4992 -m state --state NEW -j REJECT
## allows all udp in, but avoids conntrack
COMMIT
# Save the rules above as iptables.test.rules
iptables-restore < iptables.test.rules
# Test that you can connect to your machine
# Install iptables rules to be applied when interface is brought up
cd /etc/
iptables-save > iptables.rules
chmod 600 iptables.rules
cd /etc/network/if-pre-up.d/
wget https://raw.githubusercontent.com/torservers/server-config-templates/master/iptables-restore
chmod +x iptables-restore
#!/bin/bash
##############################################################################
#
# Port knocking script
# Based on:
# http://www.microhowto.info/howto/
# implement_port_knocking_using_iptables.html
#
# This script knocks on the four ports defined below with UDP packets:
# * Ports on which to knock:
# 1. KNOCK1: 23456
# 2. KNOCK2: 34567
# 3. KNOCK3: 45678
# 4. KNOCK4: 56789
# and connect to an SSH server listening on port 4992
#
# Usage:
#
# ./knock.sh && ssh --p4492 myuser@myserver
#
#
# please note that if you are using anotherserver as a proxy you can do:
#
# ssh myproxyserver 'bash -s' < knock.sh && ssh myserver
#
# Provided that you have configured ssh properly, e.g. putting the following
# in your ~/.ssh/config:
#
# ---
# Host myserver
# Hostname 123.123.123.123
# User myuser
# Port 4992
# ProxyCommand ssh myproxyserver -W %h:%p
# ---
#
##############################################################################
# Set "bash strict mode"
# See:
# http://redsymbol.net/articles/unofficial-bash-strict-mode/
set -euo pipefail
IFS=$'\n\t'
# myserver IP address
HOST='123.123.123.123'
# ports to knock
PORT1=23456
PORT2=34567
PORT3=45678
PORT4=56789
echo "KNOCK1"
echo -n "*" | nc -q1 -u $HOST $PORT1
echo "KNOCK2"
echo -n "*" | nc -q1 -u $HOST $PORT2
echo "KNOCK3"
echo -n "*" | nc -q1 -u $HOST $PORT3
echo "KNOCK4"
echo -n "*" | nc -q1 -u $HOST $PORT4
echo "CONNECT"
5c5
< Port 22
---
> Port 4992
14d13
< HostKey /etc/ssh/ssh_host_ed25519_key
20c19
< ServerKeyBits 1024
---
> ServerKeyBits 2048
28c27
< PermitRootLogin without-password
---
> PermitRootLogin no
33c32
< #AuthorizedKeysFile %h/.ssh/authorized_keys
---
> AuthorizedKeysFile %h/.ssh/authorized_keys
64c63
< X11Forwarding yes
---
> X11Forwarding no
88c87,93
< UsePAM yes
---
> UsePAM no
>
> # Disable reverse DNS lookups.
> # See:
> # https://unix.stackexchange.com/questions/56941/
> # what-is-the-point-of-sshd-usedns-option
> UseDNS no
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.