DDoS Protection OutlineThe WhyGenerally speaking, there is not much an individual can do to protect against a large scale DDoS attack without expensive hardware to handle it. They can increase the size of attack they can handle but without proper hardware it won't make much of a difference; their server will still fail. However, in a peer to peer network with many nodes, each little bit adds to the threshold that the network can handle. If every node can handle an additional 20,000 bytes per second in a 200 node network, that is an additional 4,000,000 bytes per second of an attack the peer to peer network can handle and that makes a difference.
The WhatIn this outline I will provide tips and links with instructions on how to get the most DDoS resilience out of your node so that together we may have a stronger, safer, NXT Network.
The BasicsChoose a Simple OS (Difficulty Level: Very Easy)The less you have on your OS, the less security flaws there are to exploit. It is simple as that. Always install the bare minimum of the OS you are using. Typically, for Linux, this will be the server edition and/or will have "minimal" in the name.
Use Full OS Encryption if Possible (Difficulty Level: Very Easy - Very Hard)Full OS encryption (with a strong password) will help prevent attackers from compromising your machine by remotely accessing your hard drive. On some OSs, this is something you are asked if you want to do during the install process, on others you have to do it manually.
TODO: Give specific details on how to do this for a variety of OSs.
No Wifi (Difficulty Level: Very Easy)Wifi cards are limited in how much data they can handle per second, and while your wifi may seem fast, it is slow compared to a direct hookup with your router. A direct hookup to the internet can handle a significantly larger attack than a wifi hookup. If you are connected directly to your router, it is likely that the only limit to handling a DDoS attack will be set by your computer itself rather than the connection it has.
DNS Handling (Difficulty Level: Intermediate)DNS is short hand for "Domain Name Server." They are the servers that translate "
www.nxtforum.org" into an IP address that your computer can connect to. Normally, your computer has to wait for a an IP address from its DNS every time it visits a website. This slows it down and eats up bandwidth which makes it more vulnerable to DoS attacks. In this section, I will outline how to prevent this as much as possible as well as secure DNS requests with encryption to help prevent spying. This is done with two programs, DNSMasq and DNSCrypt.
Setting up and configuring DNSCryptFirst you need to install DNSCrypt. This can be done in three commands. But first, switch over to the root account:
sudo su
Then enter the following three commands:
add-apt-repository ppa:anton+/dnscrypt
apt-get update
apt-get install dnscrypt-proxy
Now that DNSCrypt is installed, need to make a special user for it to run as. Just in case the home directory we are going to use doesn't exist, we will make it with the following command:
mkdir /run/dnscrypt
If you get an error stating that the directory already exists, it is fine; move on to making the user.
The username of this user should be ordinary and not indicate that it is used for DNSCrypt in any way. Name it after a friend or a pet and add 2-4 numbers at the end or beginning. Now enter the following command and replace "[Username]" with the username you decided on:
adduser --system --quiet --home /run/dnscrypt --shell /bin/false --group --disabled-password --disabled-login [Username]
You will probably get a warning saying that the user doesn't own the home directory. Fix this with the following line of code (again replacing "[Username]"):
chown [Username]: /run/dnscrypt
Now we need to configure DNSCrypt. Open the configuration file using nano with the following command:
nano /etc/default/dnscrypt-proxy
When you are modifying lines in this file, if they start with any number of #'s, delete the #'s. Only do this for lines you are changing!
First, change the line that starts off "user=" to contain the username you chose. It should look like "user=[Username]" when you are done.
Now, change the line "local-address=" to have a value other than "127.0.0.1" so it won't conflict with DNSMasq once that is set up. Keep it in the "127.0.0.X" family (where X is a number between 0 and 255) so it won't accidentally conflict with a real IP address. "127.0.0.2" would work just fine. Write this down somewhere as you will need it when setting up DNSMasq.
Next, you go to a website:
https://github.com/jedisct1/dnscrypt-proxy/blob/master/dnscrypt-resolvers.csvOn this website, search for a DNS server that is, most importantly, marked as having "No Logs" and having "DNSSEC Validation." Among these candidates, select the server you think is closest to you geographically.
Back in nano, find a line starting with "resolver-address=" that does not have a # in front of it (there should be one without any #'s). Change the value after the equals sign to the value in the "Resolver Address" column on the web page I liked you to that lines up with with the DNS server you chose. Do the same thing for "provider-name" and "provider-key" using the values from the "Provider Name" and "Provider Key" columns on the web page respectively.
Save the file (Ctrl+O) and exit nano (Ctrl+X). Next, we want to make sure that this runs on startup. Enter the following command:
nano /etc/rc.local
Add the following two lines BEFORE the line that says "exit 0" but replace "[Username]" with the username you chose for DNSCrypt:
mkdir /run/dnscrypt
dnscrypt-proxy --daemonize --user=[Username]
Save the file (Ctrl+O) and exit nano (Ctrl+X). You should be good to go!
Installing and Configuring DNSMasqThe next, step is getting DNSMasq set up. First we have to install it:
apt-get install dnsmasq
Next, we have to configure it. Enter the following to bring up its configuration file in nano:
nano /etc/dnsmasq.conf
Press Ctrl+W and type in "listen-address=" then press "Enter" to find the right line. If there are any #'s in the same line, go ahead and delete them. Change the line to look like this:
listen-address=127.0.0.1
Press Ctrl+W and type in "proxy-dnssec" then press "Enter" to find if the line exists. If it does exist and any number of #'s are in the same line as it, delete the #'s. If it doesn't exist, start a new line and type it in. If it exists with no #'s, leave it alone. Either way, you should have a line that looks like this when you are done:
proxy-dnssec
Next, do the exact same thing for the that phrase "no-resolv" and by that I mean Ctrl+W search it; if you find it delete any #'s and if you don't make a new line and type it in. Finally, Ctrl+W and look for "server=" to set the last configuration option. Look around and make sure that there isn't line starting like that without any #'s around. Then pick a line that starts with "server=" and set it equal to the IP address you wrote down when configuring DNSCrypt.
Save the file (Ctrl+O) then exit nano (Ctrl+X). DNSMasq is now configured to run through DNSCrypt!
Final StepsNow, all you need to do is restart DNSCrypt:
restart dnscrypt-proxy
then restart DNSMasq:
/etc/init.d/dnsmasq restart
and... It should be working! To test it, enter the following command:
dig nxtforum.orgIf you get anything other than an error, it worked; you are now running you own DNS Cache with information received over and encrypted connection! If you do get an error for some reason (like not following instructions), enter the following two lines of code and start over:
apt-get purge dnsmasq
apt-get purge dnscrypt-proxy
iptables Configuration (Difficulty Level: Intermediate)If your server has iptables on it... USE IT! I know digital ocean uses it and any linux systems will have it. If you are going to configure iptables for your server, do it in the order I provide here. The order is important.
Flush current iptables rulesJust to be safe, get rid of all current iptables rules so you can set up the new rules do this by issuing the command:
iptables -F
Drop common attacksIssue the following code to drop common attacks with iptables:
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
This code drops all incoming null packets, all incoming syn packets, and all incoming XMAS Packets
Allow local hostYou want port 7874 to be open to accept information and you may also want local host to be open if you plan on using the API or UI servers on your node.
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
Limit the number of connections a single IP address can haveThank you, rigel, for this improvement!
Use the following code to limit the number of connections a single ip address can have and how many they can make per second:
iptables -A INPUT -m connlimit --connlimit-above 10 -j DROP
iptables -A INPUT -m hashlimit --hashlimit-name LIMIT --hashlimit-burst 10 --hashlimit-above 1/second --hashlimit-mode srcip --hashlimit-htable-expire 10000 -j DROP
(Optional) Open Port 7874If you want your node to be public, you will have to open up port 7874.
iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 7874 -j ACCEPT
TODO: Find the standard strings that are sent using from peers using NXT and drop all others to maximize security on port 7874.
(Optional) Allow PingsThis (I think) is no threat. Someone correct me if I am wrong. Not allowing pings may affect your ability to be found, but again, I am not sure so I need to be corrected here.
-A INPUT -p icmp -m icmp --icmp-type 8 -m state --state NEW -j ACCEPT
Default DropFor maximum security, you want to drop all other packets sent.
-A INPUT -j DROP
Modify TCP Settings (Difficulty Level: Intermediate)It is possible to modify your TCP settings to increase DDoS protection even further than iptables alone could. Thank you to rigel for this whole section!
Open sysctl Configeration FileYou will want to use a basic text editor for this. Most Linux machines come with nano as a command line text editor. We will use it for these instructions.
nano /etc/sysctl.conf
Change SettingsAdd the following lines to the file:
net.ipv4.tcp_fin_timeout = 20
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_probes = 4
net.ipv4.tcp_keepalive_intvl = 15
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 3
net.ipv4.tcp_max_orphans = 16384
net.ipv4.tcp_max_tw_buckets = 16384
net.ipv4.tcp_retries2 = 10
net.ipv4.tcp_tw_reuse = 1
net.ipv4.ip_local_port_range = 16384 65535
Then save the file and exit nano.
Apply ChangesOnce you have exited nano, issue the following code to apply the changes you just made:
sysctl -p