bert hubert <ahu@ds9a.nl>

Simple Packet Signing (SPS)
---------------------------

Ok, I have an itch to scratch. I have a laptop wich travels a lot and
therefore has a very dynamic IP address. Even our home has a dynamic IP
address, within a certain range. I currently grant broad access to my
servers so that I am able to connect from all those IP addresses to ssh, to
open up my access lists, so I can ssh to the rest of the network.

Also, I am sometimes in a situation where I need to trust an IP address
which can be forged by lots of untrustworthy people. Everybody in the
chain from me to that server might be able to acquire my IP address, and
thus gain access to my servers!

*  Sometimes I just wish that I would be able to simply sign my packets, and
*    have my access lists recognise the signature, and accept my traffic. 

This is what I want:

On computer 'ahu', which we trust:

ahu:~# iptables -A OUTPUT -d secured-subnet -j SIGN --key /etc/sps/hostkey

On the side that wants to grant access to hosts/networks you trust:

filt:~# iptables -A INPUT -m verify --key /etc/sps/ahu.key -j UNSIGN

It's that simple. 

Not so simple
-------------

Want more? Check this:

file:~# iptables -N AHU   # rules for people who sign with ahu's key
file:~# iptables -A AHU -j UNSIGN   # remove key, possibly decrypt
file:~# iptables -A AHU -j ACCEPT   # ahu can access everything 

filt:~# iptables -A INPUT -m verify --key /etc/sps/ahu.key -j AHU
filt:~# iptables -A INPUT -m verify --key /etc/sps/office.key -j ACCEPT

This allows you to have separate access lists for different keys.

Less signing, more connection tracking
--------------------------------------

ahu:~# iptables -A OUTPUT -d secured-subnet -m state --state NEW -j SIGN --key /etc/sps/hostkey

filt:~# iptables -A INPUT -m verify --key /etc/sps/ahu.key -j ACCEPT
filt:~# iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

This only signs the first packet in a connection, which is then established,
after which packets don't need to be signed anymore to pass.

Trusting entire networks
------------------------

If you want to trust an entire network, have the router sign outgoing
packets to your secured subnet:

ahu:~# iptables -A FORWARD -d secured-subnet -j SIGN --key /etc/sps/hostkey

But wait, isn't this just like IPSEC?
-------------------------------------

Well, it looks somewhat like it. What I'm proposing is implementing the AH
layer, but then differently. The last option, trusting entire networks,
requires IPSEC to go into tunneling mode which is not quite trivial. Also,
there is no lightweight IPSEC implementation available right now.

IMNSHO opinion, IPSEC should be implemented in 'Bump in the Stack' mode, and
iptables is an exquisite way of doing so, requiring no kernel changes, only
a few modules.

IPSEC may well be the way to go. Perhaps we can implement SPS over the
existing AH header, with the simple configuration as described above. Who
knows, I'm very open to suggestions.

I have *no* grudge at all against IPSEC, it's just that I don't like to
patch my kernel, same goes for the people I know who maintain the
accesslists - your router is a *vital part* of the network. 

Please talk to me if you think I'm doing the wrong thing.

Use a tunnel!
-------------

Tunnels require additional IP addresses, and again access to my network so
you can see the tunnel. 

How would you do this then?
---------------------------

Well, I started out by signing packets in the IP Options field in the IP
header - which is actually the right place to do it. Noone would be hurt by
superflous signatures, you could sign opportunistically.

However, it turns out that many routers out there think they should drop
packets with IP options they don't understand. Some routers even drop
packets with NOP IP options! So this is not an option.

This means that we need to encapsulate and use another IP protocol type.

Signing
-------

To sign a packet, the SIGN target receives the packet, shifts the
payload downwards, and inserts an SPS header. We then sign the payload, and
enter the signature in the SPS header, and return the packet to the kernel
for sending.

Verifying
---------

The verify module only matches if the IP protocol is of type SPS. It
verifies the signature and if it's correct, jumps to the indicated target

Unsigning
---------

Before a kernel can understand a packet, the signature needs to be removed.
This is what the UNSIGN module does - currently it is called STRIPSPS.

Crypto
------

As yet undecided. Both the SIGN target and the verify module could handle
multiple algorithms. I just bought Applied Crypto (get it, it's good) and
will let it guide me. Expect simple password based signatures (shared
secret), as well as full blown public key.

Encryption
----------

Yeah, while we're at it, we could do that as well. Problem is that right now
we only sign outgoing packets to a known destination. This would need a
conntrack helper module to also be notified of return packets in the same
stream.

Open standard
-------------

If this takes off, I'll write RFCs and stuff.

Results so far
--------------

It works. I can succesfully sign packets and transmit them large distances
over the internet.

Earlier MTU worries have been put aside - if the packet gets too large,
Linux fragments it on transmission. If the side that has to do the
verification has the ip_conntrack module loaded, it will automatically
defragment before SPS ever sees the packet. This has been verified.

Open questions
--------------

On the crypto side, can it be as simple as this? Do we need protection
against replay attacks? Do we perhaps need more complicated session key
negotiations to prevent key leakage?

	We will use a Message Authentication Code (MAC) that consists of a
	one-way hash of the key, some padding, the message and again the
	key. According to Applied Crypto, this is secure. See also RFC 2104.

How do we implement encryption/signing of the reverse? Some conntrack magic
is needed here. We can be succesful without this, but it will help.

Fragmenting packets is not pretty. Should we mess with MSS to prevent the
sending side from building big packets? 

If we do asymmetric keys, is it imperative to negotiate a session key first?
Or would we then go overboard? After reading Applied Crypto for a bit, I
fear that we need to create a symmetric session key if we want to use
asymmetric keys :-( Asymmetric signing can take *seconds*, it appears.

$Id: PLAN,v 1.8 2001/08/29 23:05:15 ahu Exp $