Techniques — Simple Linux networking
Back to techniques

Based on Ubuntu 10.04 (a variety of Debian Linux).

Get a basic firewall up

sudo ufw default deny
# sudo ufw allow http # for web servers; this is port 80
# sudo ufw allow https # for web servers; this is port 443
sudo ufw allow ssh # this is port 22
sudo ufw logging on
sudo ufw enable
sudo ufw status

Basic network information

# Interface information
netstat -i -e
# Info for "eth0"
sudo ethtool eth0
# Other diagnostics
netstat --tcp [--listening] [--numeric] [--programs]
nmap -v localhost

Send e-mail via a TLS-secured e-mail host

sudo apt-get install sendemail

sendEmail \
        -xu USERNAME \
        -xp PASSWORD \
        -o tls=yes \
        -u "SUBJECT" \
        -m "MESSAGE"

Set up a reverse SSH connection

For example: you have a public-facing host with SSH access, called publichost; you have a private (e.g. conventional ISP) host called privatehost; you want to be able to log in to privatehost from publichost.

  1. Install the autossh package.
  2. Call the following script e.g. /usr/local/bin/autossh_tunnel_publichost on privatehost and run /usr/local/bin/autossh_tunnel_publichost start regularly (e.g. every 10 minutes) from privatehost's /etc/crontab. That gets the connection going. Download as autossh_tunnel_PUBLICHOST or see below:
    #! /bin/sh
    # Author:	Andreas Olsson <>
    # Version:	@(#)  0.1  27-Aug-2008
    # Modified by RNC 14/10/9
    # For each tunnel; make a uniquely named copy of this template.
    # autossh monitoring port (needs to be unique on publichost)
    MPORT=5124 ### amend as necessary
    # the ssh tunnel to setup (also needs to be unique on publichost)
    TUNNEL="-R 5024:localhost:22" ### amend the "5024" bit as necessary
    # remote user
    RUSER="myusername" ### amend as necessary
    # remote server
    RSERVER="publichost" ### amend as necessary
    # keyfile
    KEYFILE="/home/myusername/.../mykeyfile" ### amend to point to a real SSH private key (which will be accepted by publichost for this username)
    # You must use the real autossh binary, not a wrapper.
    NAME=`basename $0`
    DESC="the tunnel"
    test -x $DAEMON || exit 0
    #RNC# export AUTOSSH_PORT=${MPORT}
    #RNC# ASOPT=${TUNNEL}" -f -N "${RUSER}"@"${RSERVER}
    ASOPT="-M "${MPORT}" -N -f -i "${KEYFILE}" "${TUNNEL}" "${RUSER}"@"${RSERVER}
    #	Function that starts the daemon/service.
    d_start() {
    	start-stop-daemon --start --quiet --pidfile $PIDFILE \
    		--exec $DAEMON -- $ASOPT
    	if [ $? -gt 0 ]; then
    	    echo -n " not started (or already running)"
    	    sleep 1
    	    start-stop-daemon --stop --quiet --pidfile $PIDFILE \
    		--test --exec $DAEMON > /dev/null || echo -n " not started"
    #	Function that stops the daemon/service.
    d_stop() {
    	start-stop-daemon --stop --quiet --pidfile $PIDFILE \
    		--exec $DAEMON \
    		|| echo -n " not running"
    case "$1" in
    	echo -n "Starting $DESC: $NAME"
    	echo "."
    	echo -n "Stopping $DESC: $NAME"
    	echo "."
    	echo -n "Restarting $DESC: $NAME"
    	sleep 1
    	echo "."
    	echo "Usage: $SCRIPTNAME {start|stop|restart}" >&2
    	exit 3
    exit 0
  3. Then from publichost, you can execute ssh localhost -p 5024 (assuming you kept the main port as 5024 in your copy of the script).

SSH authorization

To generate a public/private SSH keypair, and authorize it:

ssh-keygen -t rsa -f /home/thisuser/.ssh/localhost-to-remotehost-rsync-key
# ... enter a blank passphrase if you want to use unattended operation
# ... makes localhost-to-remotehost-rsync-key (PRIVATE = LOCAL) and (PUBLIC = REMOTE)
# ... now ensure the private key (without the .pub extension) is only readable by the user
# ... then move the public key to the remote host:
scp /home/thisuser/.ssh/ remoteuser@remotehost:/home/remoteuser/

# ON REMOTE: log in by hand (ssh remoteuser@remotehost), then:
cd ~
if [ ! -d .ssh ]; then mkdir .ssh ; chmod 700 .ssh ; fi
mv .ssh/
cd .ssh/
if [ ! -f authorized_keys ]; then touch authorized_keys ; chmod 600 authorized_keys ; fi
cat >> authorized_keys

ssh remoteuser@remotehost
# ... should now authenticate with the keyfile

# Now you're ready for automated operation. But...

Can now restrict operation further using .ssh/authorized_keys on the remote. For details see this helpful CU Engineering page. You can restrict the valid hosts that this key will work for. Additionally, you can restrict the commands it can run. If you intend to run it as root (which you should avoid if it is not absolutely necessary), then you should restrict as much as possible, including the IP addresses allowed and the functions allowed through SSH. For example, (1) in /etc/ssh/sshd_config, specify PermitRootLogin forced-commands-only (as opposed to the better default of PermitRootLogin no); (2) in your /root/.ssh/authorized_keys file, have lines like e.g.

from="myvalidhost.myvaliddomain",command="/usr/local/bin/validate_ssh_command",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa the_key_itself root@myservername

... then have a /usr/local/bin/validate_ssh_command script (downloadable as validate_ssh_command or see below) that only allows certain things through, e.g. this for rsync and unison:

		echo "Rejected"
		echo "Rejected"
		echo "Rejected"
		echo "Rejected"
		echo "Rejected"
		echo "Rejected"
	rsync\ --server*)
	unison\ *)
		echo "Rejected"

When things go wrong, open a temporary port on the server and use /usr/sbin/sshd -d -p PORTNUM on the server to watch what's happening, and ssh HOST -p PORTUM -v -v on the client.

Watch a web page

Create the following script as /usr/local/bin/watch_web_page. In /etc/crontab, run it regularly, passing it (1) a URL, (2) a temporary file where it can keep a copy of the web page, and (3) a program to run if the page changes (e.g. to e-mail you about it). Download as watch_web_page or see below:


# $1 = URL to watch.
# $2 = File to use for temporary storage of a copy.
# $3 = Program to run (with URL as parameter) when watched page changes.

# RNC, 18 June 2010.


if [ -f $FILEONE ];
	echo "Page previously stored."
	wget -O $FILETWO $URL >/dev/null 2>&1 && ( echo "Web page fetched using wget." ) || ( echo "Failed to fetch web page."; exit 1 )
	cmp $FILEONE $FILETWO && ( echo "No change to page." ) || ( echo "Page changed."; $PROGRAM $URL )
	echo "Page not previously stored."
	wget -O $FILEONE $URL >/dev/null 2>&1 && ( echo "Web page fetched using wget." ) || ( echo "Failed to fetch web page."; exit 1 )
exit 0

Local backup and synchronizing files across hosts

Where possible, synchronize user-to-user. Where the backup system has to be able to cope with files owned by any user/group with any permission, use root.

Mount a filesystem using SSH

# mount:
sshfs hostname:/directory/ temp/

# unmount:
fusermount -u temp/

VNC to a dynamic-IP-address Windows machine from a fixed-IP-address Linux host

The prototypical problem: someone needs help with their home Windows computer but has Internet access via a conventional broadband ISP; their computer is therefore not directly accessible to the wider Internet. You have access to a decent machine (viz., a UNIX-based computer with a static IP address). We'll call the computers winbox and linuxbox. Prerequisites:

Method 1: VNC Server to Listening VNC Viewer (directly)

The simplest of the three methods for the Windows user (no PuTTY required). The VNC server has to be on the Windows machine (because that's the one we want to look at). However, the VNC server can initiate the connection to the viewer (which is helpful if the VNC server is on a machine with a dynamic and inaccessible IP address, while the viewer is on a proper static IP address).

Method 2: VNC Server to Listening VNC Viewer (via SSH)

In this method, we connect the same way round (server on the Windows box initiates the connection to the viewer on the Linux host), but we tunnel it through SSH, so only port 22 (SSH) needs to be exposed to the outside world by the Linux host.

Method 3: VNC Viewer to VNC Server (via SSH)

In this method, the VNC connection is initiated by the viewer. To make the server visible to the viewer, it needs to be tunnelled via an SSH connection (which is initiated by the Windows box in our hypothetical situation).

NX to an XFCE system

Desktop: Unix / custom. Settings: Run...: /usr/bin/xfce4-session. Options: New virtual desktop.

Printing from a Windows guest OS in VirtualBox to an underlying CUPS printer

See and There's no need to open port 631 on your firewall, as the Linux host will see requests from the VirtualBox guest OS as being local.

Valid HTML 4.01 Transitional
Valid CSS