So as a lot of you know that I’ve done a lot of hosting in my time. With that comes the territory that is a cPanel server. cPanel is a fantastic and well-thought-out product. That being said, any cPanel server that’s been kicking around on the net for longer than a couple of months is likely constantly being attacked by Chinese botnets trying to gain access to cPanel boxes for use with their “aggressive marketing” scanning your ports looking for anything listening on 2087 and get all excited when they find a WHM cPanel alive and well.
The son of a dead cocoa merchant needs my help retrieving a locked box containing $21.3 million USD. Give me your PayPal password.
cPanel comes with cPHulk installed and enabled by default. This is actually a really great bit of kit and I recommend everyone use it as it will watch over all kinds of services not just the WHM panel (The owner’s control panel not your customers for those playing the home game.)
BROTIP: This guide is only to secure the 2087 root site and SSH behind a VPN. Your cPanel customers/users will still be able to access all resources from the outside like normal including their cPanel (port 2083).
I had my cPHulk setup to notify me when there was an attempt at a brute force attack thinking naively when I started out that this would be a few and far between thing. I really wasn’t worried about it as my root passwords are ridiculously long and complex… But it’s annoying. Manually adding attack subnets using my iPhone was tiresome and monotonous.
So I figured, there has to be a way…
There is. In my Google searching I found that you can use the WHM built-in Host Access Control panel which is a spiffy GUI front end for hosts.allow and hosts.deny. (but it puts deny statements in hosts.allow.) I was like cool, I can just block the internet on a per service basis. But then I realized that I have a dynamic IP at home (though it hasn’t changed in over a year, it could change at any moment.) And what if I want to access WHM on my iPhone over my carrier’s network? Clearly, I’m going to have zero idea what my IP address would be and I’d have to leave a large swath of IP range owned by my ISP and mobile carrier open to WHM access. I then had the thought… Why not just hide all of the “admin” services behind a VPN?
My first thought of course was using an IPSec VPN from my home network to my hosting servers. But then I thought, “Has IPSec ever gone smoothly when Windows is involved?”
The next thought was PPTP, it’s simple to install and configure in Linux and it actually doesn’t suck duck nuts on Windows. So here’s how you setup your cPanel server to hide services behind a PPTP VPN.
First thing we need to install PPTPd on your Linux box.
- yum install ppp (but it’ll likely already be installed)
- cd usr/local/src
- wget http://poptop.sourceforge.net/yum/stable/packages/pptpd-1.3.4-2.el6.x86_64.rpm (if you’re on 32 bit linux, stop reading now and go fix your box.)
- rpm –Uhv pptpd-1.3.4-2.el6.x86_64.rpm
- See above except the file name is different: pptpd-1.3.4-2.rhel5.x86_64.rpm
Ubuntu (who runs cPanel on Ubuntu?)
- apt-get install pptpd
Because this shit doesn’t write itself, people.
Next, we need to add some IP settings.
Head over /etc/
Scroll to the bottom and uncomment the first set of IPs.
Here’s the deal with this. There’s not a lot of documentation on this. I highly recommend that you make the local IP and the remote IPs different than any private network you may be connecting from and of course make it a private network (172.16.x.x, 10.x.x.x, 192.168.x.x) so as not to interfere with any production environments.
remoteip 192.168.33.100-200 (you can specify a single IP or a range here.)
Next we need some creds. Edit the chap-secrets file which should look something like this.
# client server secret IP addresses
Username * Password *
Here we’re putting in the username which works on any server (*) with the password specified from any IP address (*) with tabs in between. Resist the urge to get cute and start trying to filter source/destination IP. You’ll just end up crying yourself to sleep.
BROTIP: Do NOT use the same password as your root password. Think about it. IF someone were to get this password, one of your customers somehow read chap-secrets, the farthest they’d get into your system is where you were before all of this. Besides, if someone can read your chap-secrets file, you’ve got bigger problems. But alas, you don’t want to hand them your root password. Don’t do it. I warned you. If you do it, your shit will turn black and fall off. For cereals….
There are other options we can add to PPTP none of which apply here because we’re not doing PPTP for connectivity we’re doing it for security. Move along.
Let’s bust out some iptables.
BROTIP: replace eth0 (green) with your device name, it may be different if you’re using a physical host with multiple NICs.
iptables -A INPUT -i eth0 -p tcp –dport 1723 -j ACCEPT
iptables -A INPUT -i eth0 -p gre -j ACCEPT
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -A FORWARD -i ppp+ -o eth0 -j ACCEPT
iptables -A FORWARD -i eth0 -o ppp+ -j ACCEPT
service iptables save
service iptables restart
service pptpd restart
BROTIP: depending upon your hardware, you may not have autocreated the /dev/ppp device and you’ll fail at connecting to the VPN. TEST YOUR VPN NOW!!!! If you secure your server and you’re not sure if you’re VPN works first, you will be hosed unless you have physical access.
Create the device with: mknod /dev/ppp c 108 0
Next, we’re going to lock ourselves out of our servers… Well not really, but you’ll see. There are two ways to do this. First, if you’re a sissy, log into WHM as root and head to the GUI or do it man-style through the cli since if you’re following this guide, you should already be there.
This file has a really simple format. It’s 3 simple fields but the order of the lines is important for not locking yourself out of your server. Additionally, the two main services we’re going to focus on here is whostmgrd (WHM cPanel) and SSHd (your SSH access). Which reminds me, if you’re running telnet on your cPanel server, just go ahead and post your IP and root password in the comments below and I’m sure one of our many talented readers will fix that for you.
whostmgrd : 192.168.33.0/255.255.255.0 : allow
sshd : 192.168.33.0/255.255.255.0 : allow
whostmgrd : ALL : deny
sshd : ALL : deny
Ok, so look closely here, people. My allow statements are ABOVE my deny statements. The file is read from the top down and STOPS once a matching statement is found. So you want your allows to be above your denies almost always. If you hose this up, I hope you have physical access to the box.
So as soon as you save that file it’s going to take effect. You should probably proof read that bad boy, then have your wife look at it and maybe your cat before saving because you will lose normal internet access to it on those ports.
If all goes well when you try to login to your server on the WHM port you get politely told to fuck off.
So now when all the bot nets are porting around trying to find your WHM server, they’re going to find the port open yes, but they’re not going to even be given the opportunity to load on your system by attempting to log in.
Now in order to log in as root on your box either through SSH or WHM, you need to connect to the box with a PPTP VPN accessing the site using the internal IP you configured in pptpd.conf (e.g. 192.168.33.1.) Damn nifty, eh? How to do that is a bit beyond the scope of this guide. Maybe I should have put this bit at the beginning. Fuck it, I’ll link you.