Practical way to implement prevention of IP Spoofing
The first thing you need to do is to understand the kinds of attacks you want to protect against. I don't think anything can give you a better understanding of the attacks than writing code to perform the attacks.
The three classes of attacks I know of in relation to IP spoofing are these:
- Resource consumption on the server
- Reflection attacks
- Attacks on accountability
I'll describe each of them in more detail. The resource consumption class of attacks means the server will be receiving a flood of packets, most of which have spoofed source IP. Since the spoofed IP addresses can have any distribution picked by the attacker, there is no telling spoofed packets from legitimate packets. The server only has resources to handle some number of these packets, the more packets the attacker sends, the smaller fraction of legitimate packets can be handled by the server.
The typical attack in this class is the SYN flood, which was news decades ago. The resource it consumes on the server is mainly memory to keep state of each TCP connection.
SYN cookies are designed to protect exactly against this attack. They take the concept of a cookie and squeeze it into the TCP handshake. A cookie is short value that the server sends to the client with the only purpose, that the client can send it back to the server. This proves that the client received the cookie. The usual spoofing scenario only allows the attacker to send packets from a spoofed IP, not receive packets that the server sends to this IP.
SYN cookies do lose a little bit of functionality from TCP. This was a consequence of needing to be compatible with existing TCP clients and at the same time not use memory on the server before the client ass proven the IP address by returning the cookie.
Port knocking fails in both design goals mentioned above. It is not at all transparent to the client. Additionally, it also requires state to be stored even after the first (knock) packet has been sent to the server. Port knocking is simply not designed to mitigate IP spoofing, it is designed for an entirely different purpose. If you do want efficient protection against IP spoofing and you are willing to require a software update on the client, there are much more efficient approaches.
Reflection attacks are aimed at consuming network bandwidth rather than resources on the server itself. Such attacks put the IP of the victim in the source IP and any suitable server in the destination IP. Once the server receive the request it will reply to the spoofed source with a reply which may be much larger than the request. This allows the attacker to flood a victim with much more traffic than it itself is sending.
Multiple UDP based services can be used in this class of attacks. DNS and NTP are well known services, which when receiving a small request may send a large reply.
The most efficient method to protect against reflection attacks is for the server to never send more than one packet in response to a request from an IP address, which has not previously been proven correct, and that response must not contain any more bytes than the request. TCP is usually consider immune to reflection attacks, but UDP based services can be vulnerable.
The third class of attacks is those where you complete a full transaction on the server using one spoofed IP throughout the communication. All logs on the server will indicate this transaction was performed by the spoofed IP. This is usually considered to be a purely theoretical attack.
Usually communication, where this really matters, is done over TCP. The attacker has to guess a 32 bit sequence number to even establish the connection. The attacker may also have to guess the size of each reply from the server. And if encryption is used, the attacker may even have to guess part of the contents. Moreover the attacker has to complete the transaction before the host being spoofed has had time to send an error message to the server, which would close the connection.
How to test the attacks
Setting up a small network of machines, it is not difficult to spoof the IP of any host on the Internet and send packets from that IP to your own server. At the same time you can arrange for the routing table to route replies to those towards the Internet. With that setup, you have a realistic network to test IP spoofing. Remember to only spoof IP addresses, which are not allowed to be announced through BGP, such that you don't cause problems for somebody with the reflected packets.
Once you have the setup ready an ordinary TCP or DNS client is sufficient to send spoofed packets towards the server. An actual flood would require a bit more effort to setup, but it's not hard.
How to protect DNS against spoofing
First of all if you have a DNS server, you can detect that it is being used in a reflection attack. A reflection attack will cause an ICMP error to arrive after the server has sent a reply to spoofed IP.
What can you do to mitigate the attack? First of all, you can keep track of proven client IP addresses and spoofed IP addresses. Obviously most IP addresses will be in the category of don't know. When you receive an ICMP error in response to a DNS reply, the IP address is put in the category of spoofed IP addresses. When an IP has entered that group mitigations must be put into effect.
To mitigate the attack the DNS server send a reply containing just the request but no actual reply. Additionally the truncated bit must be set. This will tell the client to retry the request using TCP. A successful request over TCP will prove that the IP is that of an actual client and move the IP address to the set of proven IP addresses.
Should the set of known spoofed IP addresses grow larger than you want to track, you simply stop tracking it and switch to use the mitigation even on IP addresses, where the spoofed state is unknown.
How to protect all protocols against spoofing
Writing service specific code for every single service running on UDP does not seem to be the correct way to protect against spoofing. There ought to be a service independent way to protect against spoofing.
I don't think you can do that in a completely backward compatible way. But let's assume we could put something new between the IP layer and the transport layer that would help against spoofing, and let's assume consider spoofing enough of a problem to deploy such protection, then what could such protection look like?
I have an idea based on an IPv6 extension header to achieve this. I drafted some more details a few months ago. If you are up to the task of actually implementing it in an open source IPv6 stack, then I'd be happy to translate my draft to English.