In the last coupled of days, I've been writing an API. Nothing to complicated, just a few resources for some of my company customers grab info, directly into their system.
So I need SSL for securing the data, the main problem is that I use Squid as a reverse proxy to forward the URL for each server.
After fooling around I discover that the package that come with Ubuntu (10.04, I only use the LTS versions) does not came with SSL support out of the box, so we need to compile from the source.
I use version 2.7, but this instructions work with v3.
Verify it doesn’t have ssl support:
/usr/sbin/squid -v
You need to add some repositories in /etc/apt/sources.list
deb-src http://pt.archive.ubuntu.com/ubuntu lucid main restricted universe multiverse
deb-src http://pt.archive.ubuntu.com/ubuntu lucid-updates main restricted universe multiverse
deb-src http://security.ubuntu.com/ubuntu lucid-security main restricted universe multiverse
Change the URL accordingly to your country.
First you need to install the following:
cd /usr/src
sudo apt-get install libssl-dev
sudo apt-get install devscripts build-essential fakeroot
sudo apt-get source squid
sudo apt-get build-dep squid
sudo apt-get install libcppunit-dev
sudo apt-get install libsasl2-dev
sudo apt-get install cdbs
You need to edit the rules
file
cd squid-2.7.STABLE7/debian
pico rules
Now look for the line that contains: # Configure the package.
Before the last line add: --enable-ssl \
Save and exit.
debuild -us -uc
dpkg -i squid_2.7.STABLE7-1ubuntu12.3_i386.deb squid-cgi_2.7.STABLE7-1ubuntu12.3_i386.deb squid-common_2.7.STABLE7-1ubuntu12.3_all.deb
Change the version of Squid accordingly to yours.
You should have Squid with SSL support.
Before continue just a reminder. You should have Squid installed in a different machine than your webserver, because if you don´t, you have to change the ports that Apache or other webserver listen to. If you don´t do this Squid listen to 3128 and 3129 instead of 80 and 443, and don´t redirect correctly.
Any old machine is suffice, I can tell you that my is a Pentium II, and works like a charm.
Now you have 2 options:
1 - Create a self signed certificate
2 - Buy one.
I choose the second because I find that Commodo have a one that cost only 12€. It´s call Positive SSL and you can find it here.
If you choose the first one find instructions for creating a self-signed certificate here.
Now let´s configure Squid to accept SSL connections.
First backup the current configuration:
sudo cp /etc/squid/squid.conf /etc/squid/squid.conf.bak
Again you have 2 options here:
1 - configure globally to accept any SSL connection
2 - configure for each redirection.
If you choose the second one, you must have one certificate per sub-domain, or buy one that includes also sub-domains. (They are expensive)
I did choose the first and did a litle trick for my API. More on that later.
So edit the config file:
pico /etc/squid/squid.conf
Now add at the top of the file:
https_port 443 cert=/etc/squid/ssl-cert/my_cert.crt key=/etc/squid/ssl-cert/my_key.key defaultsite=www.mycompany.pt vhost
Of course you need to change that line to your configuration.
So that line says that every connection that came via https, port 443, Squid will load that particulate certificate. You don´t have to install it on your webserver because it´s Squid that handle that. Quite nice indeed.
So now you have to write the redirect rules. They are quite simple:
cache_peer 192.168.0.1 parent 80 0 no-query originserver name=server_1
cache_peer_domain server_1 www.mycompany.pt
acl sites_server_1 dstdomain www.mycompany.pt
http_access allow sites_server_1
What this means.
You are telling Squid that every request that comes to www.mycompany.pt it redirects to the server 192.168.0.1, it works for http or https.
Now I have a subdomain api.mycompany.pt
The rules are the same:
cache_peer 192.168.0.1 parent 80 0 no-query originserver name=server_2
cache_peer_domain server_2 api.mycompany.pt
acl sites_server_2 dstdomain api.mycompany.pt
http_access allow sites_server_2
The request goes to same IP, because that server is configure with several vhosts.
So now we have a problem. The certificate is only valid for the www.mycompany.pt.
Let´s do a little trick. The API is REST based so it receives several requests.
I'm going to use a GET request as an example:
The URL is:
http://api.mycompany.pt/api/rest?method=test&key=123456&testsearch=myparticularsearch
So if we use https
it will throw a certificate authentication error. So my solution is to use a link. I create a new directory in the dir where the www.mycompany.pt
resides.
cd /var/www/mycompany
mkdir secure
cd secure
ln -s api /var/www/api/deploy/public/api/
Now if we use https://www.mycompany.pt/secure/api/rest?method=test&key=123456&testsearch=myparticularsearch
the certiciate works fine.
I can have the site for the API, with the documentation and so on, and a secure link for the data.
It´s not the perfect solution, but it works just fine.
I will have a problem when the new site for www.mycompany.pt is finished. Because it will be using ZF - MVC. And secure will be a module name.
I´ll deal with that later......