Thursday, September 16, 2010

Secure SSH Host Deployment

How to Setup a Secure SSH Server


A remotely accessible internet connected device is extremely convenient if you need to grab a file on the go or use a computer with extra horsepower from a mobile device. However, increased accessibility to distributed information comes at the cost of an increase in risk . Hosting an internet facing service like SSH instantly exposes the host server to prowling attackers scanning for open ports to attack.


If you think this is an exaggeration, just try connecting your computer (sans firewall and router) directly to the internet for 20 minutes with the following options setup in your iptables startup script (/etc/init.d/iptables):


iptables -A INPUT -j LOG --log-ip-options

iptables -A INPUT -j DROP


iptables -A INPUT -j LOG --log-tcp-options

iptables -A INPUT -j DROP


To view the connections just type:


$ tail -f /var/log/messages


If this experiment feels like too much work you can Google the results of similar trials on blogs and forums. The bottom line is that /var/log/messages will quickly balloon in size as connection attempts are made to your IP address. Although convenient, you certainly don't need your server exposed to potential compromise as a result of an SSH service. To securely deploy a remote service, such as SSH, appropriate care needs to be taken to ensure that malicious users are kept out and legitimate traffic is allowed in. Secure deployment of an SSH service requires a few tools :


1. OpenSSH Server - $ sudo apt-get install openssh-server

2. Psad - $ sudo apt-get install psad

3. (optional) fail2ban - $ sudo apt-get install fail2ban


The OpenSSH Server package contains the SSH daemon software. The OpenSSH client is installed by default, so no need to install it twice. Psad is a Port Scan Attack Detector that works in conjunction with syslogd and IPtables to analyze log files in realtime and block malicious hosts attempting to scan your network. Fail2ban is an optional piece of software that observes login attempts over SSH services and blocks hosts with repeated failed login attempts over a short period of time.


sshd Configuration:


OpenSSH provides an encrypted means of remotely accessing a computer. It was developed to replace clear-text solutions such as tenet and the *nix r-services (rlogin, rsh, etc). It provides encryption for the entire session, including password exchange, and has feature that allow easy tunneling through SOCKS proxies. The ssh daemon stores all configuration details in the file /etc/ssh/sshd_config. Most of the default settings are secure as is, however a few require tweaking:


$ sudo vi /etc/ssh/sshd_config


Port 80 #(or 443)

Protocol 2 #protocol 1 is deprecated and prone to unauthorized data insertion attacks

PermitTunnel yes #Set to 'no' if SSH will not be used to tunnel VNC

AllowTcpForwarding yes #Set to 'no' if SSH will not be used to tunnel VNC

PermitRootLogin no #don't want anyone to brute force the root account

PermitEmptyPasswords no #all accounts should have passwords


Restart sshd:


$ sudo /etc/init.d/ssh restart


There you have it, the service is running. The configuration settings are fairly straight forward, aside from the port settings. It may seem counter intuitive to setup an SSH server on port 80 or 443 - but there is a reason and it has nothing to do with the security of the SSH server. Some SSH server tutorials indicate the service should be configured on a non-standard port, such as 2200 or something like that, in order to deter attackers. This is just obfuscation and does not increase the overall security of the host. A knowledgeable attacker will see through this front and realize that an SSH service is operating on the port.


The port setting is changed to 80 or 443 because most corporate (and even some public) networks have egress filters and will typically only allow outbound traffic to ports 80 and 443 (HTTP and HTTPS services). An egress filter inspects outbound network traffic and verifies the destination ports are allowed out of the network. Egress filters are the reason why most people have problems using chat services from their office. The standard ports most chat services operate on are blocked by the outbound firewalls of your corporate network. So, by configuring your SSH service on port 80 or 443 you can access your SSH host from inside a corporate network. This trick offers some nice benefits, such as bypassing corporate firewalls as well as encrypting your traffic.


** If you have a web server operating on ports 443 or 80, try using TCP 53. DNS typically operates over udp/53, but some DNS servers accept queries over tcp/53 and as such most egress filters will allow outbound traffic over this port.


psad Configuration:


psad is a tool used to identify and actively block remote IPs attempting to port scan your network. It does this in real time by working in conjunction with iptables and syslogd. With syslogd capturing inbound packets and iptables dropping malicious traffic, psad monitors changes to /var/log/syslog for inbound connection attempts. When a number of connections from the same host exceeds a defined threshold psad dynamically blocks the offending IP address using iptables.


To begin, psad must be configured with syslogd so inbound packets are analyzed. To do so edit syslog.conf (man syslog.conf for additional info):


$ sudo vi /etc/syslog.conf


add the following line to the file:


kern.info |/var/lib/psad/psadfifo


This indicates that all kernel messages with priority info to warning are to be saved to the file psadfifo. Restart syslogd:


$ sudo /etc/init.d/syslogd restart


Configuration details for psad are found in the file /etc/psad/psad.conf. For our purposes, we're most interested in security, so I'm going to ignore settings used for email notification. The following settings should be added to psad.conf so the service can use iptables to block scan attempts:


$ sudo vi /etc/psad/psad.conf


CHECK_INTERVAL 5; #number of seconds between syslog checks

PORT_RANGE_SCAN_THRESHOLD 1; #number of scanned ports before psad reacts

ENABLE_PERSISTENC Y;

ENABLE_SYSLOG_FILE Y;

IPT_WRITE_FWDATA Y;

IPT_SYSLOG_FILE /var/log/messages;

MIN_DANGER_LEVEL 1; #logging stats at danger level 1

ENABLE_AUTO_IDS Y;

AUTO_IDS_DANGER_LEVEL 1; #i'm paranoid, if you send me 5 packets on 2 different ports i block you

AUTO_BLOCK_TIMEOUT 86400; #one day in seconds, set it to whatever you want, again, overly paranoid on my part

IPTABLES_BLOCK_METHOD Y;


IPT_AUTO_CHAIN1 DROP, src, filter, INPUT, 1, PSAD_BLOCK_INPUT, 1;

IPT_AUTO_CHAIN2 DROP, dst, filter, OUTPUT, 1, PSAD_BLOCK_OUTPUT, 1;

IPT_AUTO_CHAIN3 DROP, both, filter, FORWARD, 1, PSAD_BLOCK_FORWARD, 1;


The rest of the settings can be tweaked and researched at your leisure, but these are the core details we're interested in. From here we can restart the service:


$ sudo /etc/init.d/psad restart


iptables Configuration:


Finally we need to configure the firewall rules. At a minimum psad requires the following rules be added to the iptables firewall startup script:


iptables -A INPUT -j LOG

iptables -A FORWARD -j LOG


Firewall rules are not for the faint of heart. It's enough to make your head spin thinking about TCP flags on NEW vs ESTABLISHED packets and when to DROP and what to ACCEPT and on what chains. If you're not careful it's pretty easy to deny legitimate as well as malicious traffic. Thank god for the internet and the smart people who use it. Pasted below is a sample firewall.sh script:


$ sudo vi /etc/firewall.sh


#!/bin/bash

IPT="/sbin/iptables"

echo "Starting IPv4 Wall..."

# -F flushes the specified table, -X deletes the chain

$IPT -F

$IPT -X

$IPT -t nat -F

$IPT -t nat -X

$IPT -t mangle -F

$IPT -t mangle -X

modprobe ip_conntrack

# get a list of bad IPs and store them

BADIPS=$(grep -v -E "^#|^$" /var/log/psad/auto_blocked_iptables)

PUB_IF="eth0"

# unlimited, accept packets through the loopback interface

$IPT -A INPUT -i lo -j ACCEPT

$IPT -A OUTPUT -o lo -j ACCEPT

# DROP all incoming traffic, default to deny all policy

$IPT -P INPUT DROP

$IPT -P OUTPUT DROP

$IPT -P FORWARD DROP

# block all bad ips

for ip in $BADIPS

do

#on chain INPUT for all packets of source $IP drop them

$IPT -A INPUT -s $ip -j DROP

#on chain OUTPUT for all packets of destination $IP drop them

$IPT -A OUTPUT -d $ip -j DROP

done

# sync

# log all new packets with something other than the SYN bit set that exceed 5 packets/minute

$IPT -A INPUT -i ${PUB_IF} -p tcp ! --syn -m state --state NEW -m limit --limit 5/m --limit-burst 7 -j LOG --log-level 4 --log-prefix "Drop Syn"

# drop all NEW packtes with something other than the SYN bit, i.e non standard port scan

# think nmap -sX (xmas scan), -sF (FIN scan), -sA (ACK scan), -sN (null scan),etc.

$IPT -A INPUT -i ${PUB_IF} -p tcp ! --syn -m state --state NEW -j DROP

# LOG/DROP all fragments other than the head because there is no way to identify the source IP

$IPT -A INPUT -i ${PUB_IF} -f -m limit --limit 5/m --limit-burst 7 -j LOG --log-level 4 --log-prefix "Fragments Packets"

$IPT -A INPUT -i ${PUB_IF} -f -j DROP

# block bad stuff

# look at ALL packet flags and drop those with the FIN, URG, and PSH flags set

# look for nmap -sX scan I think

$IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP

# look at ALL packet flags and drop those packets with the SYN, ACK, FIN, RST, URG, and PSH flags set

# nmap --setflags URGACKPSHRSTSYNFIN

$IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL ALL -j DROP

# drop packets with no flags set, nmap -sN scan (null scan)

$IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL NONE -m limit --limit 5/m --limit-burst 7 -j LOG --log-level 4 --log-prefix "NULL Packets"

$IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL NONE -j DROP # NULL packets


# look at only SYN and RST flags, if they are set drop them, nmap --scanflags SYNRST

$IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags SYN,RST SYN,RST -j DROP

# drop, nmap -sX scans, at least a variant of that scan

$IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags SYN,FIN SYN,FIN -m limit --limit 5/m --limit-burst 7 -j LOG --log-level 4 --log-prefix "XMAS Packets"

$IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP #XMAS

$IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags FIN,ACK FIN -m limit --limit 5/m --limit-burst 7 -j LOG --log-level 4 --log-prefix "Fin Packets Scan"

$IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags FIN,ACK FIN -j DROP # FIN packet scans

$IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP

# Allow full outgoing connection but no incoming stuff

# allow all existing connections to persist

$IPT -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT

# allow outbound connections to continue

$IPT -A OUTPUT -o eth0 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

# allow ssh only

$IPT -A INPUT -p tcp --destination-port 443 -j ACCEPT

$IPT -A OUTPUT -p tcp --sport 443 -j ACCEPT

# also allow 4445 for simple (unencrypted) net cat text/file transfers

# this is my own thing you can comment these out

# see my other post about how to use netcat for simple file transfers

$IPT -A INPUT -p tcp --destination-port 4445 -j ACCEPT

$IPT -A OUTPUT -p tcp --sport 4445 -j ACCEPT


# drop incoming ICMP ping pong stuff, drop ICMP packets

$IPT -A INPUT -p icmp --icmp-type 8 -m state --state NEW,ESTABLISHED,RELATED -j DROP

$IPT -A OUTPUT -p icmp --icmp-type 0 -m state --state ESTABLISHED,RELATED -j DROP

# No smb/windows sharing packets - too much logging

$IPT -A INPUT -p tcp -i eth0 --dport 137:139 -j REJECT

$IPT -A INPUT -p udp -i eth0 --dport 137:139 -j REJECT

# Log everything else

# *** Required for psad ****

$IPT -A INPUT -j LOG

$IPT -A FORWARD -j LOG

$IPT -A INPUT -j DROP

exit 0


Copy and past the iptables script into a Bash shell script /etc/firewall.sh. We'll also need an iptables flush script to restart the firewall if any rules need to be quickly cleared; for instance to unblock all blocked IPs. Thankfully, this one is easier to understand. Copy and past this script into /etc/flush_firewall.sh:


$ sudo vi /etc/flush_firewall.sh

#!/bin/sh

# Set the default policy

iptables -P INPUT ACCEPT

iptables -P FORWARD ACCEPT

iptables -P OUTPUT ACCEPT


# Set the default policy for the NAT table

iptables -t nat -P PREROUTING ACCEPT

iptables -t nat -P POSTROUTING ACCEPT

iptables -t nat -P OUTPUT ACCEPT


# Delete all rules

iptables -F

iptables -t nat -F


# Delete all chains

iptables -X

iptables -t nat -X


# End message

echo " [End of flush]"


Once the firewall.sh and flush_firewall.sh scripts have been created, a service script needs to be created. To begin, create a new script, /etc/init.d/firewall:


$ sudo vi /etc/init.d/firewall


ETVAL=0


# To start the firewall

start() {

echo -n "Iptables rules creation: "

/etc/firewall.sh

RETVAL=0

}


# To stop the firewall

stop() {

echo -n "Removing all iptables rules: "

/etc/flush_firewall.sh

RETVAL=0

}


case $1 in

start)

start

;;

stop)

stop

;;

restart)

stop

start

;;

status)

/sbin/iptables -L

/sbin/iptables -t nat -L

RETVAL=0

;;

*)

echo "Usage: firewall {start|stop|restart|status}"

RETVAL=1

esac


exit


Once the script is created, it's properties need to be changed to ensure that it is executable:


$ sudo chmod 755 /etc/init.d/firewall


The script then needs to be linked to the appropriate run level in order to startup as a service on boot. To so do enter the following command:


$ sudo update-rc.d firewall defaults


That should do it. Load up the service by typing:


$ sudo /etc/init.d/firewall start


Verify that the rules have been loaded using the following:


$ sudo /etc/init.d/firewall status


You should get output similar to this:


Chain INPUT (policy DROP)

target prot opt source destination

fail2ban-ssh tcp -- anywhere anywhere multiport dports https

PSAD_BLOCK_INPUT all -- anywhere anywhere

ACCEPT all -- anywhere anywhere

LOG tcp -- anywhere anywhere tcp flags:!FIN,SYN,RST,ACK/SYN state NEW limit: avg 5/min burst 7 LOG level warning prefix `Drop Syn'

DROP tcp -- anywhere anywhere tcp flags:!FIN,SYN,RST,ACK/SYN state NEW

LOG all -f anywhere anywhere limit: avg 5/min burst 7 LOG level warning prefix `Fragments Packets'

DROP all -f anywhere anywhere

DROP tcp -- anywhere anywhere tcp flags:FIN,SYN,RST,PSH,ACK,URG/FIN,PSH,URG

DROP tcp -- anywhere anywhere tcp flags:FIN,SYN,RST,PSH,ACK,URG/FIN,SYN,RST,PSH,ACK,URG

LOG tcp -- anywhere anywhere tcp flags:FIN,SYN,RST,PSH,ACK,URG/NONE limit: avg 5/min burst 7 LOG level warning prefix `NULL Packets'

DROP tcp -- anywhere anywhere tcp flags:FIN,SYN,RST,PSH,ACK,URG/NONE

DROP tcp -- anywhere anywhere tcp flags:SYN,RST/SYN,RST

LOG tcp -- anywhere anywhere tcp flags:FIN,SYN/FIN,SYN limit: avg 5/min burst 7 LOG level warning prefix `XMAS Packets'

DROP tcp -- anywhere anywhere tcp flags:FIN,SYN/FIN,SYN

LOG tcp -- anywhere anywhere tcp flags:FIN,ACK/FIN limit: avg 5/min burst 7 LOG level warning prefix `Fin Packets Scan'

DROP tcp -- anywhere anywhere tcp flags:FIN,ACK/FIN

DROP tcp -- anywhere anywhere tcp flags:FIN,SYN,RST,PSH,ACK,URG/FIN,SYN,RST,ACK,URG

ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED

ACCEPT tcp -- anywhere anywhere tcp dpt:https

ACCEPT tcp -- anywhere anywhere tcp dpt:4445

DROP icmp -- anywhere anywhere icmp echo-request state NEW,RELATED,ESTABLISHED

REJECT tcp -- anywhere anywhere tcp dpts:netbios-ns:netbios-ssn reject-with icmp-port-unreachable

REJECT udp -- anywhere anywhere udp dpts:netbios-ns:netbios-ssn reject-with icmp-port-unreachable

LOG all -- anywhere anywhere LOG level warning

DROP all -- anywhere anywhere


Chain FORWARD (policy DROP)

target prot opt source destination

PSAD_BLOCK_FORWARD all -- anywhere anywhere

LOG all -- anywhere anywhere LOG level warning


Chain OUTPUT (policy DROP)

target prot opt source destination

PSAD_BLOCK_OUTPUT all -- anywhere anywhere

ACCEPT all -- anywhere anywhere

ACCEPT all -- anywhere anywhere state NEW,RELATED,ESTABLISHED

ACCEPT tcp -- anywhere anywhere tcp spt:https

ACCEPT tcp -- anywhere anywhere tcp spt:4445

DROP icmp -- anywhere anywhere icmp echo-reply state RELATED,ESTABLISHED


Chain PSAD_BLOCK_FORWARD (1 references)

target prot opt source destination


Chain PSAD_BLOCK_INPUT (1 references)

target prot opt source destination


Chain PSAD_BLOCK_OUTPUT (1 references)

target prot opt source destination


Chain fail2ban-ssh (1 references)

target prot opt source destination

RETURN all -- anywhere anywhere

Chain PREROUTING (policy ACCEPT)

target prot opt source destination


Chain POSTROUTING (policy ACCEPT)

target prot opt source destination


Chain OUTPUT (policy ACCEPT)

target prot opt source destination


This was a lot to digest, but at this point you should have sshd, psad, and iptables all up and running. If you have a second machine, try running an nmap scan on the SSH server. If everything was configured properly the host performing the scan should be blocked. You can review blocked hosts using the following command:


$ sudo psad --fw-list


To retrieve a summary report of any offending hosts issue the following command:


$ sudo psad -S


[+] psad (pid: 24573) %CPU: 0.1 %MEM: 0.2

Running since: Tue Sep 14 09:15:36 2010

Command line arguments: [none specified]

Alert email address(es): ShawnDEvans@gmail.com


[+] Version: psad v2.1.5


[+] Top 50 signature matches:

"BAD-TRAFFIC tcp port 0 traffic" (tcp), Count: 7, Unique sources: 1, Sid: 524


[+] Top 25 attackers:

0.0.0.0 DL: 5, Packets: 418, Sig count: 0

10.0.1.5 DL: 2, Packets: 183, Sig count: 7


[+] Top 20 scanned ports:

tcp 443 10 packets

tcp 0 7 packets


udp 51413 2247 packets

udp 5353 1032 packets

udp 67 471 packets

udp 68 1 packets


[+] iptables log prefix counters:

"NULL Packets": 17


iptables auto-blocked IPs:

[NONE]


Total packet counters: tcp: 17, udp: 3751, icmp: 0


[+] IP Status Detail:


SRC: 0.0.0.0, DL: 5, Dsts: 1, Pkts: 1, Unique sigs: 0, Email alerts: 0, Local IP


DST: 255.255.255.255, Local IP

Scanned ports: UDP 67, Pkts: 1, Chain: INPUT, Intf: eth0


SRC: 1.2.3.4, DL: 2, Dsts: 2, Pkts: 183, Unique sigs: 1, Email alerts: 0, Local IP


DST: 1.2.3.3, Local IP

Scanned ports: TCP 0-443, Pkts: 17, Chain: INPUT, Intf: eth0

Signature match: "BAD-TRAFFIC tcp port 0 traffic"

TCP, Chain: INPUT, Count: 4, DP: 0, NULL, Sid: 524

DST: 224.0.0.251

Scanned ports: UDP 5353, Pkts: 166, Chain: INPUT, Intf: eth0


Total scan sources: 2

Total scan destinations: 3


[+] These results are available in: /var/log/psad/status.out


fail2ban Configuration:


To fully harden the SSH server a piece of software called fail2ban can be implemented. Fail2ban is a simple utility that monitors the authentication log files of a number of different services (ftp, ssh, http, etc) for failed login attempts. When a designated threshold of failed login attempts is exceeded for a specific service, fail2ban dynamically modifies iptables and temporarily rejects inbound packets from the offending IP address . This method isn't bullet proof. A motivated attacker could use tor (or similar software) to frequently change their source IP address, but it as a deterrent that will dramatically slow any brute-force password guessing attack. ** Depending on your psad configuration settings it's possible that an attacker submitting multiple login attempts to the SSH service would be banned by psad anyways.


The default settings for fail2ban are found in the file /etc/fail2ban/jail.conf. If you choose to leave the default settings file intact, you can copy the contents of jail.conf to jail.local. When fail2ban is started, the jail.local file supersedes jail.conf if it exists:


$ cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

$ sudo vi /etc/fail2ban/jail.local


There are a few settings which require additional tweaking beyond the default settings:


#add internal addresses if you want 192.168.1.1, however if an internal machine was compromised it would be possible to stage a brute-force attack

ignoreip = 127.0.0.1 192.168.1.1

bantime = 3600 #in seconds, change it to whatever you want

maxretry = 5 #i'm horrible with typos and have complex, far too long password that I frequently mistype, so 3 was too few.


As for the enabled services, unless you have FTP or some other service that requires authentication operating on the same host, you only need to have ssh enabled:


[ssh]


enabled = true

port = 443 # or 80 or 53 depending on the configuration of your SSH server

filter = sshd

logpath = /var/log/auth.log

maxretry = 5 #this is just here incase you want to override the default setting for a particular service


From here you can restart the service:


$ sudo /etc/init.d/fail2ban restart



Final Thoughts on Securing Remote Services:


You should now have a fairly secure SSH host running on your machine. For my purposes, I had to punch a whole through my wireless router and enable port forwarding to the static internal address and port of the SSH host. This configuration limits additional security precautions that could be implemented to further limit access to the host. My goal in configuring the SSH server was to limit the ability of attackers to detect open ports on my network, provide a minimal attack surface to detect, and provide maximum flexibility to the users of the SSH service.


A more effective means of preventing such attacks is to implement a deny all policy and only allow trusted hosts access to the remote service. For instance, if it is known that the SSH host will only be accessed from a finite number of source IP addresses it makes much more sense to deny all traffic and configure iptables to only allow traffic to a subset of white listed (trusted) IPs. A configuration based on white listed IPs is not ideal for my purposes because I anticipate accessing my SSH host from mobile devices or coffee shops where the source IP address is either highly dynamic or unknown.


Alternatively, if an SSH host is being deployed in a DMZ environment without the protection of a firewall every single inbound request to your IP address will be received by the host regardless of the destination port (provided it is between 1 and 65534). That is not to say that every inbound packet will have a corresponding response packet from your host, but that the kernel will be aware that a packet was received ; and more importantly the kernel will know the source IP and destination port of the packet. This important detail can be used to your advantage.


Consider this scenario, someone knocks on the front door of a mans home and requests entry. The man, being a paranoid jerk, refuses to unlock the door and denies the unknown person entry. The man has a very strict no entry policy in place and always rejects attempts to enter his locked door. Over time the man feels lonely and realizes that some people require entry through his locked door, but only a finite group of his close friends. If the individual requesting entry through his front door can somehow substantiate that they can be trusted entry will be granted; however the door cannot be physically opened to substantiate said trust. The paranoid man concludes that the easiest way to establish trust without physically opening the door is to establish a secret knock. A knock can be heard through the door without physically opening it. Brilliant! The man can now teach trusted individuals the secret knock and easily identify friends from foes without opening the door. Life is secure.

The very same principals can be used on a host residing in your DMZ. Given that the kernel is logging inbound packets it is possible to determine the destination port of any inbound packet attempting to access your server. Assume your network has a deny all policy in place, meaning that absolutely every packet received by your host is dropped regardless of the destination port. Now, assume that syslogd is logging all inbound packets sent to the host. It's possible to determine the destination port of every packet by analyzing the log file. In comparison to our scenario with the paranoid man, the destination port of a packet can be equated to a single knock in a sequence of knocks. Let us further assume that a service is in place to monitor the destination port of each packet received for every unique IP address in sequential order. This service will in essence produce a chronologically sorted list of destination ports for all remote hosts attempting to communicate with your host. I think by now you can see where this is going. A service capable of producing such output would be able to recognize when a known sequence of destination ports from a given source address was received by the host server, in the same sense that the paranoid man could identify a secret knock. When such a sequence is detected the source IP address of the now trusted host can be added to a temporary white list of trusted hosts and the iptables rules can be dynamically altered to reflect the exception to the deny all policy. This method of granting access to closed ports is called Port Knocking (as I'm sure you might have already guessed).


There are a number of different port knocking daemons available, but the easiest to install is knockd ($ sudo apt-get install knockd). I've personally never tried to configure the software because such a configuration would require me to open (and forward) every port on my firewall to an internal host. However, for those highly fortified few residing in a DMZ, this configuration could be just the ticket. Maybe I can do that in another post if I feel like exposing my network to the world, but frankly I just don't trust the world (or my server fortification ability) enough to do so. I hope this tutorial was informative!


Wednesday, May 19, 2010

Oprah Lookes Exactly Like Aughra (from The Dark Crystal)

I was watching The Dark Crystal not too long ago and noticed that Aughra (the three eyed creepy lady who helps out the gelflings), looks exactly like Oprah. Check out the side by side and decide for yourself:




Pretty uncanny huh?

Saturday, April 17, 2010

Denny's Pancakes, Eat Until Your Belt is Tight

Denny's has a new menu item, all you can eat pancakes for $4. For $.89 more you can make it all you can eat chocolate-chip pancakes. As many pancakes as I can eat, for less than any value meal at a fast food crap shack. Unreal.

I'm looking forward to Sunday morning already. I hope they keep this deal around for a while. At $4 a trip, it'll be fun to try to break pancake eating records every week. There's no official tally, but I'd be willing to bet my finest pancake moment was in Holmes Beach, Anna Maria Island, FLA. There's something about eating pancakes on a beach that keeps you relaxed enough to not feel rushed or full; which is probably why it's a time limited feast.

Be sure to stop by Denny's. $4. All. You. Can. Eat. Diets and health be damned.

Friday, April 16, 2010

OS X 10.5 Samsung Printer Issues

OS X Printing Issues Anyone?


I have a Samsung ML-2010 Printer. I have had numerous issues printing with this thing from OS X v10.4 to 10.5 using USB and wireless connections (via the AirPort Exreme Base station v5.7, its older). I was able to remediate all my issues, and wanted to share the advice.


Issue 1: Large Margin on Every Page


Initially I was unable to get anything to print without a giant (2 in or so) margin at the top of every page; regardless of the print settings. This was cleared up by using the Open GDI print driver available from Samsung. Get the goods here:


http://www.linuxfoundation.org/collaborate/workgroups/openprinting/macosx/samsung-gdi


You need to download and install all three packages: Foomatic-RIP, Ghostrscript for Mac, and the Samsung-GDI package. There's a particular order this should be instaled in, but I don't know it; the package installers detect the dependency failures and let you know about them, so no worries. Print using this driver and the margin problem is gone (hopefully).


Issue 2: Printer Paused (after one successful print)


* These instructions should work for any printer, not just a Samsung


In OSX 10.4 printing to the Samsung ML-2010 via the AirPort Extreme Base station was flawless. After upgrading to OS X 10.5 I was only able to print one document at a time before print functionality was halted. The print queue indicated "Printer Paused" and all attempts to resume printing would result in the same error. Removing and re-adding the printer did nothing to fix the issue. The only way (I found) to restore print functionality was to reboot the AirPort Extreme Base station.


This was a huge pain. Based on some research I did trawling google results, this issue isn't limited to Samsung printers, so these instructions should work for any printer experiencing a similar problem. To get more info on the nature of the problem I opened up the System Console and took a look at the cups error_log. This revealed that after one successful print the system was "Unable to open" the printer device. Check it out below:


[Job ???] Request file type is application/pdf.

I [16/Apr/2010:12:50:06 -0700] [Job 1] Adding start banner page "none".

I [16/Apr/2010:12:50:06 -0700] [Job 1] Adding end banner page "none".

I [16/Apr/2010:12:50:06 -0700] [Job 1] File of type application/pdf queued by "asshead".

I [16/Apr/2010:12:50:06 -0700] [Job 1] Queued on "Samsung_ML_2010" by "asshead".

I [16/Apr/2010:12:50:06 -0700] [Job 1] Started filter /usr/libexec/cups/filter/cgpdftops (PID 8326)

I [16/Apr/2010:12:50:06 -0700] [Job 1] Started filter /usr/libexec/cups/filter/pstops (PID 8327)

I [16/Apr/2010:12:50:06 -0700] [Job 1] Started filter /usr/libexec/cups/filter/foomatic-rip (PID 8328)

I [16/Apr/2010:12:50:06 -0700] [Job 1] Started backend /usr/libexec/cups/backend/mdns (PID 8329)

I [16/Apr/2010:12:50:15 -0700] [Job 1] Completed successfully.

I [16/Apr/2010:12:51:52 -0700] [Job ???] Request file type is application/pdf.

I [16/Apr/2010:12:51:52 -0700] [Job 2] Adding start banner page "none".

I [16/Apr/2010:12:51:52 -0700] [Job 2] Adding end banner page "none".

I [16/Apr/2010:12:51:52 -0700] [Job 2] File of type application/pdf queued by "asshead".

I [16/Apr/2010:12:51:52 -0700] [Job 2] Queued on "Samsung_ML_2010" by "asshead".

I [16/Apr/2010:12:51:52 -0700] [Job 2] Started filter /usr/libexec/cups/filter/cgpdftops (PID 8344)

I [16/Apr/2010:12:51:52 -0700] [Job 2] Started filter /usr/libexec/cups/filter/pstops (PID 8345)

I [16/Apr/2010:12:51:52 -0700] [Job 2] Started filter /usr/libexec/cups/filter/foomatic-rip (PID 8346)

I [16/Apr/2010:12:51:52 -0700] [Job 2] Started backend /usr/libexec/cups/backend/mdns (PID 8347)

E [16/Apr/2010:12:52:22 -0700] [Job 2] Unable to open device (read failure)!

E [16/Apr/2010:12:52:22 -0700] PID 8347 (/usr/libexec/cups/backend/mdns) stopped with status 1!

I [16/Apr/2010:12:52:22 -0700] Hint: Try setting the LogLevel to "debug" to find out more.

I [16/Apr/2010:12:52:22 -0700] [Job 2] Backend returned status 1 (failed)


So what gives? I'd put money on a driver issue with Samsung, but who cares? This has nothing to do with the solution. On a number of forums I saw people suggesting that the printer could be setup as a HP JetDirect printer rather than a Bonjour printing device in it's default, auto-configured state. Here's the gist of it:


1. Go to System Preferences -> Printers


2. Click the '+' to add a printer.


3. Rather than using the auto-detected default, click the IP tab/button at the top.


4. Select HP Jet Direct - Socket from the Protocol pull down.


5. Enter the IP address of the base station. If you don't know your IP, open Utilities > Terminal and type the following:


$ networksetup -getinfo 'AirPort' | grep Router

Router: 10.0.1.1

IPv6 Router: none


6. Select the appropriate driver from the list. For me this was the Samsung ML-2010 Foomatic/GDI, your individual milage may vary.


7. Click Add.


For some people this process apparently works. For me, it failed. If you are in the same boat that I am, roll up your sleeves, because it's time to mess with CUPS or the common unix printing system.


Configuring an HP JetDirect printer with the AirPort Extreme Base Station fails because the HP JetDirect driver is trying to connect to the wrong port. By default, an HP JetDirect server operates on port 9100. The Apple printer setup utility is aware of this standard and blindly sends all print jobs to socket://10.0.1.1:9100 (btw don't try to put that into Safari, it doesn't speak socket). However, the AirPort Base Station doesn't conform to this standard and operates its internal HP JetDirect service on port 9101. I determined this by running a port scan against the router:


$ sudo nmap -sU -sS 10.0.1.1

Starting Nmap 4.90RC1 ( http://nmap.org ) at 2010-04-16 13:09 PDT

Interesting ports on 10.0.1.1:

Not shown: 1987 closed ports

PORT STATE SERVICE

53/tcp open domain

5009/tcp open airport-admin

9101/tcp open jetdirect

10000/tcp open snet-sensor-mgmt

53/udp open|filtered domain

67/udp open|filtered dhcps

68/udp open|filtered dhcpc

123/udp open ntp

161/udp open|filtered snmp

192/udp open|filtered osu-nms

514/udp open|filtered syslog

5351/udp open unknown

5353/udp open|filtered zeroconf

MAC Address: 00:0D:93:CB:83:B6 (Apple Computer)


You might have noticed that there is no way to define a port other than 9100 in the vanilla OS X printer setup utility. To gain access to more granular configuration details you have to use CUPS. Cups is basically a Unix printing standard, and is used by Mac OS X to fulfill all your printing dreams. Following the steps below will allow you to change the default HP JetDirect port from 9100 to 9101:


* Note that these instructions assume your AirPort Extreme is at 10.0.1.1 (this might not be the case for your router configuration - make changes where necessary). Also, this information is based on OS X 10.5. The CUPS HTTP interface in OS X 10.6 is similar, but slightly different.


1. Open up Safari.


2. Navigate to http://localhost:631


3. Select the Printers tab from the upper menu.


4. Find and click the Modify Printer button.


5. The information in the Location and Description fields should be OK, so click Continue.


6. On the Device screen ensure that 'AppSocket/HP JetDirect' is selected (it might be set to 'zeroconf registered printer' if you didn't try to add a JetDirect printer beforehand). Click Continue.


7. In the Device URI you'll either see socket:// or mdsn://, in either case change it to the following (again substitute your IP if it is different):


socket://10.0.1.1:9101


Click Continue.


8. The Make/Manufacturere option box should be set correctly (assuming you used the correct driver for you printer). In my case I selected 'Samsung'. Click Continue.


9. Finally, select the correct Printer Model (i.e. Driver). I selected 'Samsung ML-2010 Foomatic/gdi (en). Click Modify Printer.


10. Thats it. You might get some redirect error because CUPS attempts to redirect to an invalid URL. Don't worry, just go back to the initial URL:


http://localhost:631/printers


11. If the printer was stopped due to an error, restart it from here.


12. Click the Jobs tab at the top. If you have any stopped jobs, either restart them or delete them and re-print.


Thats it. You should now be able to print without any additional problems. I really hope these instructions helped someone out. I was going crazy trying to fix it.