bert hubert 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 $