I have a client for which I provide a managed server. Part of that service includes managing security and access controls. In this case the only public-facing service is the Web server, so we only have ports 80 and 443 (HTTP and HTTPS) open to the world.
Web site updates are pushed to the server via a secure SSH connection, with the SSH service locked down to the Webmaster’s public IP address, which is static. This works well, except for the occasional instance where the webmaster needs to update the site while out of the office, for example from a conference or meeting.
One approach to this problem is to provide a VPN service for the client to use while off-site. This has worked well in other cases, but also has its drawbacks. We’ve found many public Wifi hotspots do not support GRE packets, which are required for a PPTP VPN connection.
The solution I came up with this morning is to write a small CGI script which I placed on the server, accessible via SSL and protected with password authentication. The concept is quite simple: it reads the source IP of the client connection, and adds an exception to the iptables firewall allowing access from that IP to the SSH service.
Step 1: configure sudoers to allow the user which runs the CGI script to execute the iptables command:
$ sudo visudo # On CentOS 5, there is a line: Defaults requiretty # If you also have an entry like this in your sudoers file, comment it out, or override it # for your Web server userid: # Defaults requiretty # or: Defaults:myusername !requiretty # Otherwise your CGI won't be able to use sudo. The latter option is safer. # Then, find the section listing users and the commands they can run. # It should start after this line: # ## Allow root to run any commands anywhere # Add an entry for your web server user. # on CentOS 5, the default user would be 'apache', but I suggest # you use suexec to configure a virtual host that runs under # a different userid specifically for running this CGI myusername ALL=(ALL) NOPASSWD: /sbin/iptables
Step 2: grab a copy of my CGI script and install it somewhere appropriate on your Web server. You may want to edit the chain, rule number and port variables to suit your ruleset. Don’t forget to password protect it, for example using this directive in a .htaccess or in your virtual host definition:
<Files "ip.cgi"> AuthType Basic AuthName "ip.cgi" AuthUserFile /var/www/html/.htpasswd Require valid-user </Files>
Step 3: hit the URL for your script, enter your login/password, and check ‘sudo /sbin/service iptables status’ to check that it has added the rule. To delete a test rule, you can use ‘sudo iptables -D <chain> <rule number>’
Step 4: I only want the exception to last until midnight, so I added an entry to root’s crontab to reload the saved ruleset at midnight:
$ sudo crontab -e # Reload iptables - flush any temporary IP restrictions 0 0 * * * /sbin/service iptables restart
And that’s all there is to it, a relatively simple solution for allowing temporary access to a server port with no administrator intervention required. The client can simply bookmark the URL for the script and run it any time access is required from outside the office.