Free DNS provides easy shared DNS hosting & URL forwarding

Saturday, November 9, 2013

Openssl - setting up a custom CA certificate, requesting and approving certificates with Subject Alternative Name (SAN)

I spent last couple of hours reading web resources, man pages and config files to get what I need: a custom CA setup that allows me to sign certificate request which include Subject Alternative Name (SAN) extensions.

Setup custom CA certificate

I started with the Ubuntu certificates guide. It explains how to setup the custom CA. I used the instructions in there, but I decided to use the default Ubuntu CA setup (which used /etc/ssl/demoCA directory).
First I edited /etc/ssl/openssl.cnf. In the CA_default section:
- I changed dir = ./demoCA to dir = /etc/ssl/demoCA (this is so that I can run openssl ca from any directory without entering full paths)
- I uncommented copy_extensions = copy  (this is required so that I can include in certificates SANs from their certificate requests)

In the req section:
- I uncommented req_extensions = v3_req

In the v3_req section
- I added subjectAltName = $ENV::subjectAltName so that I can pass SAN content via environmental variables (I found this trick somewhere on the internet, in order to avoid writing them in config files).


Finally I ran following commands to create the required files:
sudo mkdir /etc/ssl/demoCA
cd /etc/ssl/demoCA
sudo sh -c "echo '01' > serial"
sudo touch index.txt
sudo mkdir private newcerts
sudo chown 700 private newcerts
sudo openssl req -new -x509 -extensions v3_ca -keyout private/cakey.pem -out cacert.pem -days 3650 -newkey rsa:2048

Create a certificate with SAN

As indicated in the Ubuntu docs (and lots of other places):
openssl genrsa -des3 -out server.key 2048
openssl rsa -in server.key -out server.key.insecure
mv server.key server.key.secure
mv server.key.insecure server.key
env 'subjectAltName=DNS:testbox.local' openssl req -reqexts v3_req -new -key server.key -out server.csr
openssl req -in server.csr -noout -text
sudo env 'subjectAltName=DNS:testbox.local' openssl ca -in server.csr 
The signed certificate will be saved in /etc/ssl/demoCA/newcerts/.

Saturday, July 6, 2013

Improving OpenVPN thoughput

I recently faced an unusual problem (for me): an OpenVPN connection going via TCP over a fast network, which had transfered speeds of less than 2KB/s. Although I tested some other options (compression on/off, UDP, etc), none of them proved significantly faster. Moreover, I has hoping to fix the problem with as few as possible changes to clients.
Some time ago, I red about optimizing OpenVPN over Gbit networks. That post covers optimizations related to CPU bottleneck (hardware SSL support, different ciphers, etc). This was certainly not the case for me, since boxes linked via OpenVPN were mostly idle. However, that post has a very brief and accurate explanation and statement about how OpenVPN works, i.e. the data flow between source and destination.
So based on that post, I decided to try mssfix 0 (ie. disable OpenVPN packet fragmenting and leave the kernel/driver do that) and to increase tun-mtu parameter to help test speed improvements. I increased it to 32000 and I got about 150KB/s speed, then to 48000 and I got about 250KB/s, then to 60000 and I got 300KB/s. I thought "what if ...?" and I raised it to 65500. Amazingly, I got average speeds of 1.25MB/s with top speeds above 2.5MB/s.
That was cool, but had one downside: the VPN connection become unstable, with the tun0 device disappearing from the server (probably because the process that managed it crashed).
Reading further in OpenVPN man page and other posts, I decided that I should try to use OpenVPN's mssfix feature. Default value is 1500, but OpenVPN automatically reduces that in order to allow for the SSL data overhead. I decided to be on the safe size and use mssfix 1440. Heuristically, I thought I should use a tun-mtu that is a multiple of that (to help split the data in even fully-filled packets). So I used tun-mtu 64800. With these two settings on, the server proved stable and average transfer speeds went to about 850KB/s (good enough for my needs).
I should not that these transfer speeds were obtained by applying the same settings:
tun-mtu 64800
mssfix 1440
in the client config. If no changes are applied to the client configs, the transfer speed will be still unacceptable low, but still higher than before (about 5KB/s).

Wednesday, January 9, 2013

Is there any design behind Python language?

I gave Python another try (fourth or so). In the past I found it to be a terrible designed language. Lots of things in the language itself felt like they were scraped from all other existing programming languages. And the worst part, that it didn't feel familiar at all, even if you know those languages.

This time I tried Python 3. I went with the Dive Into Python 3 book (ofcourse).

Some of the weirdest things I noticed while reading:
1. Python's goal was to be a programming language that is as easy to read as plain English, right? Then why use def instead of define, why use try...except instead of try...exception. I mean, unless you know what try...except does, you'll think it will try to do something, except some other thing.

2. You add items to lists using list method like a_list.insert(), or a_list.append(), but you delete them using del keywork (del a_list[0]). What is that?

3. You define tuples with (1, 2), but (1) is not a tuple because ( ) are used for math. You need to write (1,). Makes sense, but whoever added the tuples feature did not see this coming? Were they not enough symbols on the keyboard that they had to recycle ( )?

4. You define sets with {1, 2}, but {} is a dictionary. What? Yes, for empty sets you need set().

5. Printing an empty list shows [], an empty tuple shows (), an empty dict shows {}, but and empty set shows... set()? boooh!

6. Lists have extend() and append() methods, but sets have update() and add().

7. List don't have discard() method (i.e. like remove() but doesn't raise exception), but sets do. Logic for that is?

List goes on, but I got tired of keeping track. I finished reading the book eventually (quite fast I would say considering my "go away Python" bias)  and I have to admin Python 3 is much better designed than 2.

However, it wasn't the language itself that got me hooked on the book, but it was the book itself. It's full of non-Python related technical info and generic programming tips. It ties well to other topics without going into much detail. I recommend reading it.

Sunday, November 11, 2012

Using WebScarab with existing SSL certificate

I needed to monitor/debug some HTTP and HTTPS traffic to a site from a closed source software. I had access to the real SSL certificates and via some quick DNS rewrites I was able to fool the application that the site's IP is my local address. At this point all I needed was some kind of reverse proxy that allows me to log requests as they are forwarded to the real site. I can't use Wireshark because it doesn't decode HTTPS traffic. I could have used nginx (or other similar) but I wanted something more adapted to this task. While googling I run into fiddler (only for Windows), charlesproxy (commercial), paros and its succesor ZAP (good, but listens/forwards only to one port) and others. The one that seemed to offer most features was WebScarab.

WebScarap is a Java app (selfcontained jar) that allows you to monitor HTTPS requests via it's build-in proxy. In order to handle HTTPS traffic, in the proxy listener settings you need to enable a proxy listener that forwards traffic to a HTTPS server. Something like: address=127.0.0.1, port=443, and baseurl=https://example.com:443/. 

By default, Webscarab will generate a self-signed SSL certificate for your setup. This means that browsers will complain about it and the application I was testing would refuse to use it. One can create a certs directory inside the webscarab application and put existing certficates inside that as described here. There are some things to be aware of:
  1. If you're proxying requests on privileged ports (e.g. 80 or 443), you might need to start WebScarab as root (but you already knew that, right?)
  2. Most webserver certificates come in PEM format (.crt extension) with a key file. WebScarab nees a PKCS12 format (.p12 extension) file. You can convert them with openssl:
    openssl pkcs12 -export -in example.com.crt -inkey example.com.key -certfile CertificationAuthority.crt -out example.com.p12
    
  3. When openssl asks you for a password for the .p12 file, you must enter the word password. This is hardcoded into WebScarab.
  4. The name of the .p12 file must match exactly the server name to which you are forwarding requests (as setup in the proxy listeners settings) and not the name of the server for which you are receiving requests (the two might be different). If you're forwarding to www1.example.com, then the name of the file must be www1.example.com.p12. I learned the hard way (i.e. reading webscarab code) that because I'm forwarding the requests to an IP address, the certificate file needs to be named as for that address. For example, if baseurl is https://192.168.1.1:443/ then the certificate file must be named 192.168.1.1.p12.
  5. Having a custom certificate inside the certs directory (as described in item 4) will NOT work (keep reading for a few solutions). :(
Due to item 5, I prepared everything and WebScarab was still not working. Then I noticed in the terminal window that it was throwing an exception, that the X509 key manager can not be located. After a few hours of googleing, I found this post that seems was never treated as a bug report. I edited that line of code and tried to recompile webscarab as indicated here (and other places, too).
--- a/src/org/owasp/webscarab/plugin/proxy/Proxy.java
+++ b/src/org/owasp/webscarab/plugin/proxy/Proxy.java
@@ -476,7 +476,7 @@ public class Proxy implements Plugin {
                        SSLContext sslcontext = null;
                        KeyStore ks = KeyStore.getInstance("PKCS12");
                        ks.load(is, _keystorepass);
-                       kmf = KeyManagerFactory.getInstance("X509");
+                       kmf = KeyManagerFactory.getInstance("SunX509");
                        kmf.init(ks, _keypassword);
                        sslcontext = SSLContext.getInstance("SSLv3");
                        sslcontext.init(kmf.getKeyManagers(), null, null);
Running ant build (or simply ant) to recompile webscarab failed due to many missing classes. I found out the some of the jar files that it needed to compile are not included in the git repo (maybe due to licensing terms or something). In particular, I needed to add the following jars into the lib directory (you can find them in the official webscarab jar or by googleing): bcprov-jdk15-1.45.jar, joda-time-1.6.2.jar, openid4java-nodeps-0.9.6.jar, xalan-2.7.1.jar.

After I got the jars, running ant still not finished successfully. The command that worked was: ant -lib lib build. That created a webscarab.jar file. Trying to run that jar directly (using following command) failed:
java -cp .:lib/bcprov-jdk15-1.45.jar:lib/commons-logging-1.0.4.jar:lib/flex-messaging-remoting.jar:lib/jfreechart-1.0.13.jar:lib/openid4java-nodeps-0.9.6.jar:lib/bsf-2.3.0.jar:lib/concurrent.jar:lib/htmlparser.jar:lib/jhall-2.0_02.jar:lib/tagsoup-1.0rc2.jar:lib/bsh-2.0b1.jar:lib/flex-messaging-common.jar:lib/jcifs-1.3.14.jar:lib/joda-time-1.6.2.jar:lib/xalan-2.7.1.jar:lib/chardet.jar:lib/flex-messaging-core.jar:lib/jcommon-1.0.16.jar:lib/openamf.jar:lib/xmlsec-1.4.3.jar -jar webscarab.jar  
I don't know why it failed, maybe I'm missing something. However, I opened the build directory and tried to run this:
java -cp .:../lib/bcprov-jdk15-1.45.jar:../lib/commons-logging-1.0.4.jar:../lib/flex-messaging-remoting.jar:../lib/jfreechart-1.0.13.jar:../lib/openid4java-nodeps-0.9.6.jar:../lib/bsf-2.3.0.jar:../lib/concurrent.jar:../lib/htmlparser.jar:../lib/jhall-2.0_02.jar:../lib/tagsoup-1.0rc2.jar:../lib/bsh-2.0b1.jar:../lib/flex-messaging-common.jar:../lib/jcifs-1.3.14.jar:../lib/joda-time-1.6.2.jar:../lib/xalan-2.7.1.jar:../lib/chardet.jar:../lib/flex-messaging-core.jar:../lib/jcommon-1.0.16.jar:../lib/openamf.jar:../lib/xmlsec-1.4.3.jar org.owasp.webscarab.Main
This command finally worked (ran from inside the build directory).

Update: After posting this, I found this discussion which points out that -jar and -classpath arguments are mutually exclusive. So I rewrote the first command to:
java -cp .:lib/bcprov-jdk15-1.45.jar:lib/commons-logging-1.0.4.jar:lib/flex-messaging-remoting.jar:lib/jfreechart-1.0.13.jar:lib/openid4java-nodeps-0.9.6.jar:lib/bsf-2.3.0.jar:lib/concurrent.jar:lib/htmlparser.jar:lib/jhall-2.0_02.jar:lib/tagsoup-1.0rc2.jar:lib/bsh-2.0b1.jar:lib/flex-messaging-common.jar:lib/jcifs-1.3.14.jar:lib/joda-time-1.6.2.jar:lib/xalan-2.7.1.jar:lib/chardet.jar:lib/flex-messaging-core.jar:lib/jcommon-1.0.16.jar:lib/openamf.jar:lib/xmlsec-1.4.3.jar:webscarab.jar org.owasp.webscarab.Main
That means that I'm including the webscarab.jar in the classpath and explicitly naming the main class in command line. It worked like a charm!

Update: After more poking around, I found out that I can avoid typing the long classpath by editing the manifest file inside the webscarab.jar (in META-INF/manifest.mf) and replace the current Class-Path entry with:
Class-Path: lib/bcprov-jdk15-1.45.jar lib/commons-logging-1.0.4.jar lib/flex-messaging-remoting.jar lib/jfreechart-1.0.13.jar lib/openid4java-nodeps-0.9.6.jar lib/bsf-2.3.0.jar lib/concurrent.jar lib/htmlparser.jar lib/jhall-2.0_02.jar lib/tagsoup-1.0rc2.jar lib/bsh-2.0b1.jar lib/flex-messaging-common.jar lib/jcifs-1.3.14.jar lib/joda-time-1.6.2.jar lib/xalan-2.7.1.jar lib/chardet.jar lib/flex-messaging-core.jar lib/jcommon-1.0.16.jar lib/openamf.jar lib/xmlsec-1.4.3.jar
After doing so, running WebScarab is (again) as easy as running:
java -jar webscarab.jar