Wednesday, February 18, 2009

SSL Offloading using Apache2 and reverse proxies

Where I work we have a decent size mod perl app which is quite heavy in memory usage...which then limits us how many apache children we can spawn before running out of memory.

So we have in place reverse proxies (squid) to handle static requests...this works great until we have to deal with SSL. So effectively as soon as someone hits SSL on a site the proxies are irrelevant, so even serving up static images ties up way too many apache children. So what to do about this?

SSL Offloading!

Now I could just purchase an expensive hardware SSL offloader...meh, so we decided to have apache2 do it.
Now what you will need is Apache 2 and mode-proxy-html + enable a few modules.
apt-get install apache2 libapache2-mod-proxy-html
a2enmod rewrite
a2enmod proxy
a2enmod proxy_html
a2enmod proxy_http
a2enmod ssl
Then we create a new virtual host in apache:
echo "Listen 443" > /etc/apache2/ports.conf
vi /etc/apache2/sites-available/ssloffloader
What we want is the following contents:

ServerAdmin some@emailaddress.com
SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCertificateFile /etc/apache2/ssl/somecertificate.crt
SSLCertificateKeyFile /etc/apache2/ssl/somecertificate.key
BrowserMatch ".*MSIE.*" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0
RewriteEngine on
RewriteRule ^(.*)$ http://%{HTTP_HOST}/$1 [P]

Order allow,deny
Allow from all


Replace somecert with your certificate/key
Now we need to enable the new virtualhost and restart apache to listen on port 443.
a2ensite ssloffloader
/etc/init.d/apache2 restart
With the above config what this basically does is take the request from ssl decrypt it then make a proxy request to the original host on port 80....this might sound silly at this point because port 80 would be on the same server right?....wrong.

Now lets say this is my ip layout for the servers i have:
webserver ip: 10.0.0.1
proxy ip: 10.0.0.2
ssloffloader ip: 10.0.0.3
firewall sits on 10.0.0.254

Then lets say i have www.somedomain.com pointing to 10.0.0.1

On the firewall you will need to dynamic NAT 10.0.0.1:443 to 10.0.0.3:443
so in iptables you would accomplish this by doing:
iptables -t nat -A PREROUTING -i bond0 -p tcp -d 10.0.0.1 --dport 443 -j DNAT --to 10.0.0.3:443
bond0 should be your external interface on your firewall. The firewall doesnt need to be iptables it can be any type that can do dynamic nats.

So when a request for www.somedomain.com comes in to our firewall requesting 10.0.0.1:443 the firewall nats that request to our ssl offloader on 10.0.0.3:443, which then makes a proxy request to www.somedomain.com:80 which is 10.0.0.1:80 which then returns the data to the offloader which then returns it to the firewall which then returns it to the client which is now none the wiser....(takes a breath).


Now if we want to put the squid in as a reverse proxy we need to either do more nat's or use /etc/hosts to hijack the ip for the hostname:

Nat Way:
on the ssloffloader: iptables -t nat -A PREROUTING -p tcp -d 10.0.0.1 --dport 80 -j DNAT --to 10.0.0.2:80
/etc/hosts way:
on the ssloffloader: /etc/hosts contains a line: 10.0.0.2 www.somedomain.com

Now some of you still might shudder at doing a nat like that on the firewall or you may not have that as an option.
The alternative is having the ip that the www.somedomain.com points to be on the ssloffloader, and you have to duplicate the :443 virtual host for :80, and obviously remove the ssl info on the port 80 virtual host.
You would then need to either nat from the ssl offloader to your proxy/webserver or use /etc/hosts on the ssl offloader AND the proxy as we cant rely on the dns

The other way you could do it is instead of using: RewriteRule ^(.*)$ http://%{HTTP_HOST}/$1 [P]
You could change this to be: RewriteRule ^(.*)$ http://10.0.0.1/$1 [P]

The reason i DONT do this is that your making a specific request to 10.0.0.1 as the url which is bad if your using virtual hosts on your webserver.

Sunday, February 15, 2009

Full Screen gaming with Nvidia TwinView


One thing that has always bugged me with gaming on linux, is twinview. Due to the fact of how twinview works your absolute resolution is the total of all your displays... ie
2x 1280x1024 panels would be 2560x1024. Now most full screen games (ie games without windowing) see that as your screen size is 2560x1024, so you end up having the game spread across the two monitors.....yay.
Now most games have a windowed option which is generally what i use but there are some that dont have the in game option nor do they have a runtime flag.
So to fix this we need to add another metamode in the xorg.conf

GUI Way: press ALT+F2 to get a run box dialog and type in: gksudo nvidia-settings

So you should see something like th following:
Now we need to add another metamode, click 'Advanced' then click the 'X Screen' Tab.
Click 'Add' Next to metamode, then click back to the 'Display' Tab.
Now what we want to do is turn off the second monitor, so highligh the monitor you want off for gaming then set resolution to off.
Now you should have something like the following:

From here you want to click 'Save to X Configuration File' then click 'Quit' and reload your window manager either by closing all your desktop application and hitting ctr+alt+backspace, logging out/in or restarting the machine.

The CLI way:
Using your preferred editor open up /etc/X11/xorg.conf and locate the line: 'Option "metamodes" which will be under the screen section.
simply add another mode like the following:
Original:
Option "metamodes" "DFP-0: 1280x1024 +0+0, DFP-1: 1280x1024 +1280+0"
New:
Option "metamodes" "DFP-0: 1280x1024 +0+0, DFP-1: 1280x1024 +1280+0; DFP-0: 1280x1024 +0+0, DFP-1: NULL"

This simply says that have another mode that has the first monitor at 1280x1024 and the second is off. Write the file and relog/reload X.


Controlling the metamodes:

Now that we have 2 metamodes you can see them by opening up a terminal and typing:
xrandr -q

To switch between modes use (X being which mode starting from 0):
xrandr -s X

Now when we start up a game we can run
xrandr -s 1 (to change to one panel)
and
xrandr -s 0 (to change back to two panels when we are done)

If this is too cumbersome put it in a simple bash script:
File: /usr/local/bin/launch_somegame
#!/bin/bash
xrandr -s 1
/path/to/somegame
xrandr -s 0