by Patrick Kerrigan, . Tags: Security Linux Networking
While reviewing the logs of my OpenVPN server recently, I noticed a series of suspicious looking entries that indicated that it was being used as part of a UDP reflection attack. Thankfully this is pretty straightforward to block using the built in functionality of OpenVPN and/or firewall software such as nftables. I'll cover both approaches here.
What is a UDP reflection attack?
Put simply, a UDP reflection attack is where an attacker uses your system to attack a third party, hiding their identity and making the attack appear as if it's coming from you. They do this by forging the source address of a UDP packet to make it appear to be coming from their target, then they send the packet to your system hoping to trigger a response. When your system responds it will actually be sending an unsolicited response to the attacker's target. In some cases this response can be several times the size of the request they sent to you, effectively increasing their bandwidth for the attack.
What does it look like in the log?
The log entries I was seeing looked like this:
x.x.x.x:53 TLS: Initial packet from [AF_INET]x.x.x.x:53, sid=6a22eb44 5adb63fe
x.x.x.x:53 TLS Error: TLS key negotiation failed to occur within 60 seconds (check your network connectivity)
x.x.x.x:53 TLS Error: TLS handshake failed
In this case the attacker was sending packets with a forged source address of a DNS server, with the source port set to 53 (DNS). My server would have responded to this packet to try and negotiate a connection, resulting in the targeted DNS server receiving a packet that it couldn't understand, tying up its resources.
Blocking the attack using OpenVPN's features
OpenVPN comes with a feature that can be used out of the box to block these attacks. tls-auth. The way this works is by generating a pre-shared key which is used to sign TLS handshake packets between clients and the server. If the server sees a packet like the one above which doesn't have a valid signature it ignores it, generating no response.
Begin by generating the pre-shared key:
$ openvpn --genkey --secret tlsauth.key
Next, enable tls-auth in your server configuration:
tls-auth tlsauth.key 0
And then copy the key to and enable it on all of your clients:
tls-auth tlsauth.key 1
Note here that the server configuration has "0" after the key file name, and the client configuration has "1".
Restart the server and all clients, and it should no longer respond to any client that doesn't have the tls-auth pre-shared key.
Blocking the attack using nftables
If you're unable to update all of your clients and need to stop an attack quickly, or if you'd just like an extra layer of defence, nftables can be used to filter out the majority of attack traffic.
Firstly, you can block packets to your OpenVPN server claiming to be from one of the privileged ports that the most frequently attacked server software uses by adding the below rule to your input filter chain. Legitimate clients won't be trying to connect from these ports and will be unaffected:
udp dport 1194 udp sport { 1-1024 } drop
Sometimes attacks won't be targeted at these ports and will still get through. I've noticed that the vast majority of attacks seem to be using a fixed OpenVPN session ID of 0x6a22eb445adb63fe (shown in the log message above). The following rule will drop any packets using this session ID and has all but stopped these attacks even reaching my VPN server:
meta l4proto udp udp dport 1194 @th,72,64 0x6a22eb445adb63fe drop
Note the use of "drop" rather than "reject" in these rules. This is important as it makes sure no traffic gets sent to the target system, including ICMP packets generated if you were to use "reject".
Hopefully this proves useful to others trying to block these attacks.