Tuesday, April 10, 2012

Forcing public key and password in OpenSSH

Using OpenSSH with public key authentication is quite secure. In fact, if the private key is password protected, you get 2-factor authentication -- something you know (the password) and something you have (the private key).

The Problem

However, the SSH architecture does not allow the server to force a password on the private key - The whole point, and indeed the fundamental principle in public key authentication is that the private key is unknown to the server and is managed totally by the client. There simply is no way to enforce a password! This leaves open the possibility of users deleting their private key passwords, and regressing to 1-factor authentication. The password-less private key is equivalent to a login password which is in some file in plain text on the users machine. Its not too bad since the private key is a long and strong login password, but it is written in plain-text!

A simple solution for this problem is to add another authentication step on the server, independent of the public key authentication. Sadly, in OpenSSH, only one authentication step is allowed, you can tell the OpenSSH server which authentication methods you allow, but once one of them succeeds, the user is considered authenticated.

The Solution

By utilizing another one of the OpenSSH's server options, we can add another authentication step. OpenSSH has the option to force a command AFTER authentication. This can be either done per public key in each users' authorized_keys2 file, or as a general option in the OpenSSH's sshd_config file, where is can also be selectively applied by using the Match directive.

So, armed with this knowledge, we'll force another authentication step. But which one? I would go for PAM. PAM is standard on most (if not all) GNU/Linux distributions, and has modules for a lot of authentication schemes, including OTP and of course UNIX passwords. We now need a command which will authenticate with PAM. I found this PAM example application a small, very readable application written in c so it needs very little resources. It only depends on PAM and the c stdlib, so should be pretty OS agnostic. It's simple, so it's easy to audit -- nothing shady going on!

As is, the pam application is not entirely suitable since it requires a user-name in the command line. To work around this, I put the pam binary in /usr/local/bin/ and wrap it in small shell script to pass the current user (remember that the OpenSSH server uses the user's shell to run the command)

#!/bin/sh -f
/usr/local/bin/pam "$USER" || exit 0

Save this script to /usr/local/bin/auth_res.sh, and remember to make it executable!
Add all of your 2-factor required users to the aptly named group twofactor, and then add the Match block below to the end of the sshd_config file:

Match Group twofactor
ForceCommand "/usr/local/bin/auth_res.sh"
RSAAuthentication no
PasswordAuthentication no
PubkeyAuthentication yes


Voilla! Now the users in the twofactor group will always need a private key AND to authenticate to PAM!

P.S.

Another advantage of these scheme is that the password resides on the server -- With password protected private keys, if someone get's a user's private key he can now try to bruteforce it at his leasure. In the proposed scheme, it will be harder to brute force the password since the server has limits on tiem between logins etc ...

Friday, April 16, 2010

HOWTO connect Nokia VPN to GNU/Linux

Overview

This HOWTO describes how to setup a GNU/Linux box as an IPSec gateway and a Nokia VPN client as a road-warrior so that they can talk to each other. The protocol used is IPSec with RSA authentication.
While most of the procedures described here are documented somewhere or other, I could not find them summarized under one roof, so I decided to do it myself.

To get this setup going, you will have to setup a certificate authority (CA) to issue certificates, hack the racoon IKE daemon to account for a problematic nat-t negotiation protocol by the Nokia VPN client, and configure both the racoon daemon and the Nokia vpn client so that they will be able to talk to each other and recognize the certificates.

This HOWTO assumes intermediate knowledge of GNU/Linux. You are assumed to know your shell, and have no problems in compiling packages from source. I do not assume any specific GNU/Linux distribution, just a 2.6.x kernel.

Prerequisites

GNU/Linux

  • openssl
  • ipsec-tools modified for Nokia (see this post)
  • possibly open the firewall to the IPsec packets (see this post)
  • 2.6 kernel



Nokia

(get it from Nokia)
  • Mobile VPN Client version >= 3.1
  • A compatible phone

Setting up a certificate infrastructure

Generating CA certificate

First we need to setup a certificate authority (CA) to sign all the certificates used for authenticating the gateway and clients.
# set certificate_dir to the directory you wish to keep all the certificates in:
mkdir ${certificate_dir} && cd ${certificate_dir}

# generate 2 2048 bit rsa key for the CA
openssl genrsa 2048 > ca.key

# generate the CA bookkeeping files
mkdir -p demoCA/newcerts
touch demoCA/index.txt
echo "00" > demoCA/serial 
echo "00" > demoCA/crlnumber

# generate the CA certificate and make link a hash to it
openssl req -days 1825 -x509 -new -key ca.key > ca.crt
ln -s ca.crt `openssl x509 -noout -hash -in ca.crt`.0

# generate the certificate revocation list (CRL) and hash
openssl ca -gencrl -cert ca.crt -keyfile ca.key -out crl.pem
ln -s crl.pem `openssl crl -noout -hash < crl.pem`.r0
At this stage we setup a CA which has enough function to support all of our IPSec needs.

Creating the gateway certificates

We now create the certificates for our gateway: we create a 2048 bit key, make a request and get it signed by our CA
cd ${certificate_dir}
openssl genrsa 2048 > vpngw.key
openssl req -new -key vpngw.key > vpngw.csr
openssl ca -keyfile ca.key -cert ca.crt -in vpngw.csr -out vpngw.crt

Creating certificates for Nokia clients

For each client (or group of clients), we need to create a private key and certificate in a format that Symbian will recognize:
cd ${certificate_dir}
mkdir -p Nokia/vpn

# key and certificate as for the client
openssl genrsa 2048 > client.key
openssl req -new -key client.key > client.csr
openssl ca -keyfile ca.key -cert ca.crt -in client.csr -out client.crt

# convert them into Nokia compatible format:
openssl x509 -outform der -in client.crt -out Nokia/vpn/client.cer
## MUST enter an encryption passwd! ##
openssl pkcs8 -outform DER -v2 des-ede3-cbc -topk8 -in client.key -out Nokia/vpn/client.key
# convert the CA certificate into Nokia compatible format:
openssl x509 -outform der -in ca.crt -out Nokia/vpn/ca.crt
Note: you must supply an encryption password for the client key!

Setting up IKE on GNU/Linux

Use the following raccon.conf file as a template:
#path to the certificate -- use the above defined certificate_dir
path certificate "/etc/racoon/certs";

## uncommend to get a lot of debug output
#log debug; 

#option of controlling racoon by racoonctl tool is disabled
# substituted the network address of the relevant (external) interface here
listen {
 adminsock disabled;
 isakmp 192.168.10.1 [500];
 isakmp_natt 192.168.10.1 [4500];
}

#remote section – anonymous address of road-warrior client
#any change in this section should be reflected in the Nokia vpn policy file
remote anonymous {
 exchange_mode main;
 certificate_type x509 "vpngw.crt" "vpngw.key";
 ca_type x509 "ca.crt";
 verify_cert on;
 proposal_check claim;
 generate_policy on;
 nat_traversal on;
 dpd_delay 20;
 ike_frag on;
 passive on;

 verify_identifier on;
 my_identifier asn1dn;
 peers_identifier asn1dn;
 
 #agreement proposal in IKE first phase
 proposal {
  encryption_algorithm aes 256;
  hash_algorithm sha1;
  authentication_method rsasig;
  dh_group modp1024;
 }
}

#SA information for IKE second phase
#any change in this section should be reflected in the Nokia vpn policy file
sainfo anonymous {
 pfs_group modp1024;
 lifetime time 1 hour;
 encryption_algorithm aes;
 authentication_algorithm hmac_sha1;
 compression_algorithm deflate;
}

#############################################################
## local network information
## change the settings in this section to suit your own network setup
mode_cfg {
 #starting address of the IP address pool
 network4 192.168.10.20;
 #maximum number of clients
 pool_size 20;
 #network mask
 netmask4 255.255.255.0; 
 #authentication source – user database on the system
 auth_source system;
 #configuration source – from data given in this section
 conf_source local;
 #DNS and WINS servers IP addresses
 dns4 192.168.10.1;
 wins4 192.168.10.1;
 #banner file – welcome message
 banner "/etc/racoon/motd";
}        
Things to remember
  • At the top of the file, set "path certificate" to the path of your CA and vpngw certificates
  • You would mostly need to change the things in the mode_cfg section to suit you own network. Other sections should be good as-is.
  • The "remote" and "sainfo" sections are especially tailored to fit the nokia vpn profile, so changing them will induce a change in the nokia vpn policy.

Setting up the Nokia VPN policy

The Nokia VPN policy file is really a zip archive containing two configuration files (.pol & ..pin), the client key and certificate and the CA certificate. We will construct this archive in the ${certificate_dir}/Nokia/vpn directory. The contents of the directory:
  • my-vpn.pin: policy information
  • my-vpn.pol: policy configuration
  • ca.crt: CA certificate. See above for info on how to create
  • client.cer: client certificate. See above for info on how to create
  • client.key: client key. See above for info on how to create
The policy information file contains information to be shown about the policy in the phone:
[POLICYNAME]
My First VPN Policy
[POLICYVERSION]
1.0
[POLICYDESCRIPTION]
This is my first policy. Lets see if it works
[ISSUERNAME]
Me LTD.
[CONTACTINFO]
me@me.org, +44-11111111
The policy configuration file contains all the config info. The following file is compatible with the racoon config given above:
SECURITY_FILE_VERSION: 1

[INFO]
My First VPN

[POLICY]
sa my-vpn = {
 esp 
 
 ## AES-256
 encrypt_alg 12   
 max_encrypt_bits 256
 ## SHA-1
 auth_alg 3
 identity_remote 0.0.0.0/0
 src_specific
 hard_lifetime_bytes 0
 hard_lifetime_addtime 3600
 hard_lifetime_usetime 3600
 soft_lifetime_bytes 0
 soft_lifetime_addtime 3600
 soft_lifetime_usetime 3600
 replay_win_len 0
 ## prefect forward secracy (see also IKE section)
 pfs
}



remote 0.0.0.0 0.0.0.0 = { my-vpn(**GATEWAY_IP**) }
inbound = { }
outbound = { }

[IKE]
ADDR: **GATEWAY_IP** 255.255.255.255
IKE_VERSION: 1
MODE: Main
ID_TYPE: 9
REPLAY_STATUS: FALSE
USE_MODE_CFG: TRUE
IPSEC_EXPIRE: TRUE
USE_XAUTH: FALSE
USE_COMMIT: FALSE
ESP_UDP_PORT: 0
SEND_NOTIFICATION: TRUE
INITIAL_CONTACT: TRUE
USE_INTERNAL_ADDR: TRUE
DPD_HEARTBEAT: 90
NAT_KEEPALIVE: 60
REKEYING_THRESHOLD: 90
GROUP_DESCRIPTION_II: MODP_1024

### Proposal
PROPOSALS: 1
ENC_ALG: AES256-CBC
AUTH_METHOD: RSA_SIGNATURES
HASH_ALG: SHA1
GROUP_DESCRIPTION: MODP_1024
GROUP_TYPE: DEFAULT
LIFETIME_KBYTES: 0
LIFETIME_SECONDS: 86400
PRF: NONE

### CA
CAs: 1
  FORMAT: BIN
  DATA: ca.crt

### CLient credentials
OWN_CERT_TYPE: USER
OWN_CERTS: 
  FORMAT: BIN
  DATA: client.cer
  PRIVATE_KEY_FORMAT: BIN
  PRIVATE_KEY_DATA: client.key
Notes:
  • Replace the 2 occurences of **GATEWAY_IP** with you actual gateway's IP
  • Set USE_XAUTH=TRUE for another password verification before connection
  • Set OWN_CERT_TYPE: DEVICE to allow for password-less access to the client key
Zip the above 5 files into my-vpn.vpn:
zip my-vpn.vpn bioc-vpn.pin bioc-vpn.pol ca.crt client.cer client.key
copy the my-vpn.vpn to the phone and install it. There should be no errors reported.

Enjoy the VPN

Thursday, April 15, 2010

iptable rule for allowing IPsec traffic

First, we need to open the firewall to the ESP protocol and open the IKE ports (UDP 500 and 4500). Assuming eth1 is the external interface of the firewall:
iptables --append INPUT --protocol ESP --in-interface eth1 --jump ACCEPT
iptables --append INPUT --protocol UDP --source-port 500 --destination-port 500 --in-interface eth1 --jump ACCEPT
iptables --append INPUT --protocol UDP --source-port 4500 --destination-port 4500 --in-interface eth1 --jump ACCEPT

A way to identify traffic originating from a valid IPsec session (presumably to allow it inside your network) is to use the policy module, which matches the policy used by IPsec for handling a packet.
A good catchall rule is:
iptables \
         --append INPUT \
         --in-interface eth1 \
         --match policy \
         --pol ipsec \
         --dir in \
         --jump LOG \
         --log-level debug \
         --log-prefix "IPSec "
This rule will log all packets coming from a IPsec connected peer with the message "IPSec ".

Sunday, April 4, 2010

ipsec-tools fix for Nokia VPN NAT-T

Nokia NAT-T is not compatible with the linux ipsec-tools. More info can be found in this ticket in the ipsec bug tracker.
An ugly hack which fixes this problem is provided at Nokia VPN (N97) -> raccon -> Nat-T. Since this is the only fix available, we'll go with ugly ...

Basically, the racoon daemon has to be complied without RFC nat-t support and one source line has to be changed.

I will spell out the procedures outlined above:

Using actual "raw" sources

To compile from source, get the ipsec-tools tarball from the ipsec-tools project page.

for compilation I used the following configure options:
./configure \
--enable-hybrid \
--enable-frag \
--enable-gssapi \
--enable-stats \
--enable-dpd \
--enable-fastquit \
--disable-ipv6 \
--enable-natt \
--enable-natt-versions=0,1,2,3,4,5,6,7,8 \
--enable-security-context=kernel
note the "--enable-natt-versions=0,1,2,3,4,5,6,7,8" switch

before compiling change one line in the file ipsec-tools-0.7.1/src/racoon/nattraversal.c:
--- ipsec-tools-0.7.1/src/racoon/nattraversal.c 2009-12-15 08:01:36.000000000 +0100
+++ ipsec-tools-0.7.1.patched/src/racoon/nattraversal.c 2009-10-11 13:39:36.000000000 +0200
@@ -314,7 +314,7 @@
return;
}

- if (iph1->natt_options->version < vid_numeric)
+ if (iph1->natt_options->version == 0)
if (natt_fill_options (iph1->natt_options, vid_numeric) == 0)
iph1->natt_flags |= NAT_ANNOUNCED;
}

You can now compile and install. The resulting racoon daemon will now accept nat-t connections from a Nokia VPN client

Using Debian sources

apt-get install devscripts build-essential fakeroot
apt-get build-dep racoon
apt-get source racoon
cd ipsec-tools*
dch -l local nokia
  • edit debian/rules and add the --enable-natt-versions=0,1,2,3,4,5,6,7,8 option to configure
  • patch src/racoon/nattraversal.c as per above
debuild -us -uc
dpkg -i ../*.deb

Sunday, March 21, 2010

Usefull apps for symbian

I have a Nokia E51 phone which runs symbian 3rd edition. This is a list of apps which I have installed
  • cCalc: Superior to the built in calculatro in both function and ease of use
  • cClock: Great screensaver - see the time, missed calss etc.. in a large font
  • s60SpotOn: use your phone as a light
  • KeePassJ2ME: Share passwords with the desktop application KeePass
  • Putty: I use it mainly as a port-forwarder for the Nokia built-in mail client, but if you have a device with a real keyboard, it can be used as a terminal
  • MetrO
  • Gmail
  • Google Maps

Tuesday, April 14, 2009

getting mach64 dri to work on debian

Nowadays kernels don't come with a mach64 drm module. It seems there used to be some security problems with the mach64 drm module, but this has long been fixed as claimed in in the Mach 64 DRI page. Anyway, to get it working for your current kernel, download the latest version from the freedesktop git untar it and cd into the distribution directory. after that:
cd libdrm-X.X.X/linux-core
make
Now, before installing, remove the previous modules (that came with the kernel): In debian they are usually in the
/lib/modules/`uname -r`/kernel/drivers/gpu/drm
directory. remove this directory (perhaps move it somewhere for backup) and then, back in the
libdrm-X.X.X/linux-core
directory, do
sudo make install
To see if it works, exit X, remove all the old modules:
sudo rmmod drm agpgart
and try reloading them:
sudo insmod agpgart; sudo insmod drm; sudo insmod mach64
start X and test:
glxinfo | grep render
You should have "direct rendering: Yes". If you still have "Software Rasterizer" for OpenGL, try looking through the Xorg log file at
/var/log/Xorg.0.log
. It's sometimes a memory problem. In this case, try reducing display depth. If this doesn't work, try rebooting before you give up -- sometimes the old modules just won't go away until reboot.

tuxonice for debian

Debian provides the linux-patch-tuxonice package which is in the form of a kernel patch. To use it, we must compile the kernel after applying the patch. I outline the "debian way" of doing it, which will build deb packages of the patched kernel: Make a directory for all of this kernel stuff:
mkdir kernel && cd kernel
Download the kernel source, tuxonice patch and building helpers:
sudo apt-get install linux-source-2.6 linux-tuxonice-patch build-essential fakeroot
make sure you have all the necessary dependencies for building
sudo apt-get build-dep linux-2.6
Unpack the kernel source. Use the appropriate version as installed by the above apt-get command (I will use 2.6.29 here)
tar xjvf /usr/src/linux-source-2.6.29.tar.bz2
cd linux-source-2.6.29
Build the whole thing, including patch. Note: you might have to answer some kernel configuration questions. Choose the default values unless you have a good reason not to.
fakeroot make-kpkg --added_patches tuxonice --initrd --revision=+tuxonice.1 buildpackage
You should now have the full kernel .deb files in the parent dir. Before installation, add the resume argument to the kernel command line. First find out what is the swap partition:
grep swap /etc/fstab
Now edit the /boot/grub/menu.lst file to add this to all kernels:
sudoedit /boot/grub/menu.lst
Find the line beginning with "# defoptions" and append the argument
resume=swap:/dev/hXX
where /dev/hXX is the partition from the grep command above. My line looks like this:
# defoptions=quiet resume=swap:/dev/hda5
save the file. Now install the new kernel packages:
cd ../
sudo dpkg -i linux-*-2.6.29*.deb
install the hibernate package
sudo apt-get install hibernate
after rebooting with the new kernel, use hibernate:
sudo hibernate