Linux Firewalls - Michael Rash [133]
42:5a:08:00 SRC=134.X.X.X DST=144.X.X.X LEN=60 TOS=0x00 PREC=0x00 TTL=64
ID=8662 DF PROTO=TCP SPT=47024 DPT=5005 WINDOW=5840 RES=0x00 SYN URGP=0 OPT
(020405B40402080A34FA576F0000000001030302)
Oct 30 21:39:41 iptables kernel: DROP IN=eth1 OUT= MAC=00:13:46:3a:41:4b:00:a0:cc:28:
42:5a:08:00 SRC=134.X.X.X DST=144.X.X.X LEN=60 TOS=0x00 PREC=0x00 TTL=64
ID=57989 DF PROTO=TCP SPT=59255 DPT=5008 WINDOW=5840 RES=0x00 SYN URGP=0 OPT
(020405B40402080A34FA62130000000001030302)
Oct 30 21:39:48 iptables kernel: DROP IN=eth1 OUT= MAC=00:13:46:3a:41:4b:00:a0:cc:28:
42:5a:08:00 SRC=134.X.X.X DST=144.X.X.X LEN=60 TOS=0x00 PREC=0x00 TTL=64
ID=61110 DF PROTO=TCP SPT=45344 DPT=1002 WINDOW=5840 RES=0x00 SYN URGP=0 OPT
(020405B40402080A34FA7CE70000000001030302)
Oct 30 21:39:54 iptables kernel: DROP IN=eth1 OUT= MAC=00:13:46:3a:41:4b:00:a0:cc:28:
42:5a:08:00 SRC=134.X.X.X DST=144.X.X.X LEN=60 TOS=0x00 PREC=0x00 TTL=64
ID=18165 DF PROTO=TCP SPT=49371 DPT=1050 WINDOW=5840 RES=0x00 SYN URGP=0 OPT
(020405B40402080A34FA967C0000000001030302)
Once the port-knocking server monitors the port-knock sequence out of the /var/log/messages file, iptables is reconfigured to allow temporary access to a service such as SSHD.
Port-knocking sequences can also involve other Internet protocols besides just TCP; UDP, ICMP, and even all three protocols at the same time can make up a sequence. Such a sequence might look like TCP/10001, UDP/2300, ICMP Echo Request, TCP/6005, UDP/3000.
Note
Including ICMP packets within a port-knocking sequence is taking a slight liberty with the definition of port knocking because ICMP has no notion of a "port." This is not an egregious transgression, however, because port knocking is really about encoding information within packet headers; nothing prohibits the use of ICMP within a sequence.
Indeed, fields other than the port fields within the TCP or UDP headers can also be used to encode additional information within a port-knocking sequence. For example, the 16-bit-wide checksum field in the UDP header could be manually set to a predetermined value by the port-knocking client, and a port-knocking server could be developed that would only accept the UDP packet as part of a sequence if the checksum matched this value. Listing 12-1 shows a Perl snippet that allows the user to craft the checksum field in the UDP header to a supplied hex value against an arbitrary UDP port.
Note
This script is available at http://www.cipherdyne.org/linuxfirewalls). You will need the Net::RawIP Perl module available from CPAN in order to run it (see http://search.cpan.org/~skolychev/net-rawip-0.2/rawip.pm).
Of course, manually defined checksum values are almost certainly invalid from a protocol perspective, and hence, an astute observer may notice them in network traffic. Some Ethernet sniffers such as Wireshark (see http://www.wireshark.org) automatically verify checksum values against packet headers and data and alert the user if there are any discrepancies. Netfilter (since the 2.6 kernel series) can also verify checksum values with its connection-tracking system.
$ cat craft_udp_checksum.pl
#!/usr/bin/perl -w
use Net::RawIP;
use strict;
my $src = $ARGV[0] || &usage();
my $dst = $ARGV[1] || &usage();
my $port = $ARGV[2] || &usage();
my $sum = $ARGV[3] || 0;
$sum = hex $sum;
my $raw_udp = new Net::RawIP({
ip => {
saddr => $src,
daddr => $dst
},
udp =>{}}
);
$raw_udp->set({
ip => {
saddr => $src,
daddr => $dst
},
udp => {
source => 30401,
dest => $port,
check => $sum
},
});
printf "[+] Sending UDP packet $src -> $dst ($port) with checksum %x\n",
$sum;
$raw_udp->send();
exit 0;
sub usage() {
die "[*] $0 } Listing 12-1: A UDP checksum-crafting script If you execute the above script as follows and watch the UDP packet with an Ethernet sniffer, you can clearly see the crafted checksum 0xdeed supplied from the command line (shown in bold): # ./craft_udp_checksum.pl 192.168.10.3 192.168.10.1 5005 deed # tcpdump -i eth1 -l -nn -s 0 -X port 5005