Categories
Linux

Outbound filtering of Web requests using Squid as a Proxy server

Frequently in my line of work I’ll be asked about filtering of outbound traffic from application servers. There are two schools of thought here, one is that an app server can have unfiltered access to the internet, and the other that the app server should have as little access to any resources (both inside and outside of the solution) as needed to preform its role.

This generally isn’t an issue if site to site VPNs, static IPs or similar are being used on the destination side. But what happens if your application requires access to something like Youtube, Facebook or Flickr. As these cloud services are not managed by the customer, we have no idea if they are on static IP addresses (and in the case of flickr, they do seem to change moderately frequently).

With this in mind a traditional Layer3/Layer4 firewall is only going to be able to handle this if it supports DNS resolution in its access-list set, and unfortunately (but for good reason) this is not a common feature. Cisco did introduce this to the ASA firewalls in 8.4, however I personally have not used this, so at the moment its still a bit of an unknown and I can’t recommend it to a customer.

There is however another way of doing this, whilst it might not be a perfect situation, it does at least allow you to filter outbound traffic.

The Squid proxy server has been around for quite some time and is quite a stable product, both in the forward (outbound) and reverse (inbound) HTTP proxy space. We’re going to use this to preform our outbound proxying. It is possible to use commercial products like a BlueCoat proxy, however I’m going to concentrate on the FOSS solution here.

Prerequisites

Before we start we need to have the following:

  • A Linux Server (for this example I’m going to be using CentOS 6.4, however any linux distribution should work)

Installing Squid

This is a really simple task on most linux distributions, as not only has squid been since the early 90’s, it’s also really popular! You can use the package manager to install squid on most distributions

yum install -y squid

You should get a response similar to below:

Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
Setting up Install Process
Resolving Dependencies
--> Running transaction check
---> Package squid.x86_64 7:3.1.10-18.el6_4 will be installed
--> Processing Dependency: perl(DBI) for package: 7:squid-3.1.10-18.el6_4.x86_64
--> Processing Dependency: libltdl.so.7()(64bit) for package: 7:squid-3.1.10-18.el6_4.x86_64
--> Running transaction check
---> Package libtool-ltdl.x86_64 0:2.2.6-15.5.el6 will be installed
---> Package perl-DBI.x86_64 0:1.609-4.el6 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

=====================================================================================================================================================================================================
 Package                                          Arch                                       Version                                               Repository                                   Size
=====================================================================================================================================================================================================
Installing:
 squid                                            x86_64                                     7:3.1.10-18.el6_4                                     updates                                     1.7 M
Installing for dependencies:
 libtool-ltdl                                     x86_64                                     2.2.6-15.5.el6                                        base                                         44 k
 perl-DBI                                         x86_64                                     1.609-4.el6                                           base                                        705 k

Transaction Summary
=====================================================================================================================================================================================================
Install       3 Package(s)

Total download size: 2.5 M
Installed size: 7.5 M
Downloading Packages:
(1/3): libtool-ltdl-2.2.6-15.5.el6.x86_64.rpm                                                                                                                                 |  44 kB     00:00
(2/3): perl-DBI-1.609-4.el6.x86_64.rpm                                                                                                                                        | 705 kB     00:00
(3/3): squid-3.1.10-18.el6_4.x86_64.rpm                                                                                                                                       | 1.7 MB     00:01
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Total                                                                                                                                                                942 kB/s | 2.5 MB     00:02
Running rpm_check_debug
Running Transaction Test
Transaction Test Succeeded
Running Transaction
  Installing : perl-DBI-1.609-4.el6.x86_64                                                                                                                                                       1/3
  Installing : libtool-ltdl-2.2.6-15.5.el6.x86_64                                                                                                                                                2/3
  Installing : 7:squid-3.1.10-18.el6_4.x86_64                                                                                                                                                    3/3
  Verifying  : 7:squid-3.1.10-18.el6_4.x86_64                                                                                                                                                    1/3
  Verifying  : libtool-ltdl-2.2.6-15.5.el6.x86_64                                                                                                                                                2/3
  Verifying  : perl-DBI-1.609-4.el6.x86_64                                                                                                                                                       3/3

Installed:
  squid.x86_64 7:3.1.10-18.el6_4

Dependency Installed:
  libtool-ltdl.x86_64 0:2.2.6-15.5.el6                                                                 perl-DBI.x86_64 0:1.609-4.el6

Complete!

We now would need to configure squid to start on boot

chkconfig squid on

 SSL Proxying

Squid has a rather nice feature called SSLBump which allows us to preform a Man In the Middle SSL Proxy. Privacy issues aside on this feature (after all we’re using it for servers not for end users) this is going to work for us from the server side of things. One key thing to note is we have to trust the CA, that we’re going to generate, on all applications / servers. I’m not going to cover how to do this in this post.

Normally when we create an SSL certificate we’d do this with a specific domain, however as we’re going to be proxying for all domains we’re going to use a wildcard certificate. For the “Common Name” or Server name, we need to chose “*” as the value.

In order to create the CA you can follow the following post. One point of note is to ensure that you do not do this on the Squid server, as this would mean that should the server be compromised, the CA (which is trusted on multiple servers) is now trusted as well.

We need to create the certificate using the CA script as per the above post. CA -newreq This will look similar to

Generating a 2048 bit RSA private key
...................................+++
.........................+++
writing new private key to 'newkey.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [GB]:
State or Province Name (full name) [London]:
Locality Name (eg, city) [London]:
Organization Name (eg, company) [AGrainOfSalt]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:*
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Request is in newreq.pem, private key is in newkey.pem

Once this is completed you’ll need to sign this with the CA -sign command

Using configuration from /etc/pki/tls/openssl.cnf
Enter pass phrase for /etc/pki/CA/private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number:
            c5:07:3c:dc:c5:8a:cb:ae
        Validity
            Not Before: Jul 21 16:45:48 2013 GMT
            Not After : Jul 21 16:45:48 2014 GMT
        Subject:
            countryName               = GB
            localityName              = London
            organizationName          = AGrainOfSalt
            commonName                = *
        X509v3 extensions:
            Authority Information Access:
                OCSP - URI:http://162.13.47.187:8888

            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                E8:30:79:47:75:8D:06:0C:CB:9E:84:47:65:61:D4:27:8D:61:52:D2
            X509v3 Authority Key Identifier:
                keyid:1F:F8:DB:5F:7B:FE:30:29:6F:E2:E2:C8:23:DE:5B:77:AE:82:2D:F8

Certificate is to be certified until Jul 21 16:45:48 2014 GMT (365 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            c5:07:3c:dc:c5:8a:cb:ae
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=GB, ST=London, O=AGrainOfSalt, CN=ca.test.local
        Validity
            Not Before: Jul 21 16:45:48 2013 GMT
            Not After : Jul 21 16:45:48 2014 GMT
        Subject: C=GB, L=London, O=AGrainOfSalt, CN=*
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:e0:e7:17:43:65:55:7c:da:56:46:4c:44:11:2a:
                    96:8b:b9:c0:d0:55:10:d7:f7:c7:ca:29:3b:2d:1d:
                    08:46:00:db:23:78:58:04:36:35:79:ca:5a:4f:a3:
                    81:31:c7:4c:ec:a9:07:46:af:60:98:9d:ff:06:1c:
                    58:8f:16:53:97:1b:f1:b0:17:b5:9a:5c:eb:eb:7c:
                    c5:a9:3a:93:e2:8b:23:ad:d9:54:1e:c3:99:2c:8f:
                    24:1e:b0:0b:d3:3a:2f:b3:72:79:f5:71:d9:3b:52:
                    de:78:18:c4:41:8e:dc:5c:4c:96:da:90:75:1f:21:
                    f5:83:91:30:64:11:fe:af:b1:e1:fb:4d:4a:1f:06:
                    a4:7a:b0:bf:91:bc:74:5b:27:88:e3:0d:2e:1c:3c:
                    3b:e8:6c:7b:32:90:60:c8:4c:2a:db:84:fc:c2:53:
                    7a:6c:4b:ae:45:4a:86:4a:c6:a4:88:24:33:a6:f4:
                    de:8b:56:3b:59:3f:de:92:c4:9d:f2:d4:2b:53:da:
                    62:05:94:7e:bc:f9:f8:45:53:88:56:13:30:67:ed:
                    6c:e7:0c:32:f8:53:03:49:3e:c3:c2:b6:06:83:e0:
                    d1:80:51:f4:86:f7:52:b0:7d:05:34:39:df:3b:46:
                    29:62:24:43:9a:b9:fe:ac:10:30:17:3a:e3:9a:d5:
                    ab:69
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            Authority Information Access:
                OCSP - URI:http://162.13.47.187:8888

            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                E8:30:79:47:75:8D:06:0C:CB:9E:84:47:65:61:D4:27:8D:61:52:D2
            X509v3 Authority Key Identifier:
                keyid:1F:F8:DB:5F:7B:FE:30:29:6F:E2:E2:C8:23:DE:5B:77:AE:82:2D:F8

    Signature Algorithm: sha1WithRSAEncryption
        83:2c:00:e4:58:1f:db:02:aa:a8:ff:52:45:d3:63:4f:8f:47:
        8f:65:1e:21:c7:d7:c2:76:df:03:af:64:c1:e0:2c:d5:92:44:
        35:a4:c3:02:78:0a:43:0f:ed:91:03:2a:f8:00:5c:97:f7:fc:
        6f:81:69:96:3d:c3:ce:80:f2:d2:0d:de:5c:2d:f0:27:ca:ba:
        1c:b4:09:8a:cc:b6:76:06:9f:a9:ad:a5:bf:9c:7d:9d:c5:f1:
        32:d4:d6:30:bf:bc:57:19:76:06:51:ee:e8:8b:f2:a1:4c:f7:
        69:ef:d4:96:58:4d:5a:de:98:c5:f4:17:af:b5:d2:cc:26:f0:
        69:43:72:77:4a:e7:cf:79:62:b6:a4:47:75:4b:29:dc:2f:6f:
        e6:c6:d5:1a:79:e2:1d:bf:f8:82:04:fe:d0:21:7a:8b:4e:1e:
        93:10:f4:81:d6:9d:41:9a:70:02:e7:3f:22:1a:d8:a6:2e:21:
        8a:b1:34:03:1c:83:ca:8c:19:59:1b:d6:85:f7:eb:e2:a7:32:
        d9:61:5c:e6:68:b3:ef:ba:27:4a:3f:ff:5a:6e:d2:60:36:bb:
        a2:0a:ba:aa:4f:d9:22:7e:ab:7e:78:80:87:6d:51:92:44:61:
        e6:aa:63:fa:e5:13:88:c9:f9:de:90:31:9f:28:78:ca:79:74:
        ff:0e:a4:0b
-----BEGIN CERTIFICATE-----
MIIDxTCCAq2gAwIBAgIJAMUHPNzFisuuMA0GCSqGSIb3DQEBBQUAME0xCzAJBgNV
BAYTAkdCMQ8wDQYDVQQIDAZMb25kb24xFTATBgNVBAoMDEFHcmFpbk9mU2FsdDEW
MBQGA1UEAwwNY2EudGVzdC5sb2NhbDAeFw0xMzA3MjExNjQ1NDhaFw0xNDA3MjEx
NjQ1NDhaMEExCzAJBgNVBAYTAkdCMQ8wDQYDVQQHDAZMb25kb24xFTATBgNVBAoM
DEFHcmFpbk9mU2FsdDEKMAgGA1UEAwwBKjCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAODnF0NlVXzaVkZMRBEqlou5wNBVENf3x8opOy0dCEYA2yN4WAQ2
NXnKWk+jgTHHTOypB0avYJid/wYcWI8WU5cb8bAXtZpc6+t8xak6k+KLI63ZVB7D
mSyPJB6wC9M6L7NyefVx2TtS3ngYxEGO3FxMltqQdR8h9YORMGQR/q+x4ftNSh8G
pHqwv5G8dFsniOMNLhw8O+hsezKQYMhMKtuE/MJTemxLrkVKhkrGpIgkM6b03otW
O1k/3pLEnfLUK1PaYgWUfrz5+EVTiFYTMGftbOcMMvhTA0k+w8K2BoPg0YBR9Ib3
UrB9BTQ53ztGKWIkQ5q5/qwQMBc645rVq2kCAwEAAaOBszCBsDA1BggrBgEFBQcB
AQQpMCcwJQYIKwYBBQUHMAGGGWh0dHA6Ly8xNjIuMTMuNDcuMTg3Ojg4ODgwCQYD
VR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlm
aWNhdGUwHQYDVR0OBBYEFOgweUd1jQYMy56ER2Vh1CeNYVLSMB8GA1UdIwQYMBaA
FB/42197/jApb+LiyCPeW3eugi34MA0GCSqGSIb3DQEBBQUAA4IBAQCDLADkWB/b
Aqqo/1JF02NPj0ePZR4hx9fCdt8Dr2TB4CzVkkQ1pMMCeApDD+2RAyr4AFyX9/xv
gWmWPcPOgPLSDd5cLfAnyroctAmKzLZ2Bp+praW/nH2dxfEy1NYwv7xXGXYGUe7o
i/KhTPdp79SWWE1a3pjF9BevtdLMJvBpQ3J3SufPeWK2pEd1SyncL2/mxtUaeeId
v/iCBP7QIXqLTh6TEPSB1p1BmnAC5z8iGtimLiGKsTQDHIPKjBlZG9aF9+vipzLZ
YVzmaLPvuidKP/9abtJgNruiCrqqT9kifqt+eICHbVGSRGHmqmP65ROIyfnekDGf
KHjKeXT/DqQL
-----END CERTIFICATE-----
Signed certificate is in newcert.pem

Once this is completed, ensure that newcert.pem and newkey.pem are copied to the squid server. You will then also need to remove the passphrase from the key.

openssl rsa -in newkey.pem -out sslbump.pem

Once this is done, you’ll need to then also copy the cert into the same file

cat newcert.pem >> sslbump.pem

Configuring Squid

We’re going to make a very simple squid config, allowing access from the App servers to youtube.com, but no other hosts. Replace /etc/squid/squid.conf with the following

acl manager proto cache_object
acl localhost src 127.0.0.1/32 ::1
acl SSL_ports port 443
acl Safe_ports port 80          # http
acl Safe_ports port 443         # https
acl CONNECT method CONNECT
acl youtube dstdomain www.youtube.com
acl app_server src 192.168.0.3/32

http_access deny manager
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports

ssl_bump allow app_server youtube
http_access allow app_server youtube
http_access deny all
ssl_bump deny all

hierarchy_stoplist cgi-bin ?
coredump_dir /var/spool/squid

# Listen on 3128 and do ssl-bump
http_port 3128 ssl-bump cert=/etc/squid/sslbump.pem
# Don't cache / refresh anything
refresh_pattern .               0       0%      0

 

Testing Squid

We’re going to use the curl command to test that the ACLs are working

First lets test google, this should fail. We specify the proxy with the -x flag

[[email protected] squid]# curl -I www.google.com -x 192.168.0.2:3128
HTTP/1.0 403 Forbidden
Server: squid/3.1.10
Mime-Version: 1.0
Date: Sun, 21 Jul 2013 17:23:36 GMT
Content-Type: text/html
Content-Length: 3274
X-Squid-Error: ERR_ACCESS_DENIED 0
Vary: Accept-Language
Content-Language: en
X-Cache: MISS from box1.agrainofsalt.com
X-Cache-Lookup: NONE from box1.agrainofsalt.com:3128
Via: 1.0 box1.agrainofsalt.com (squid/3.1.10)
Connection: keep-alive

As you can see we get a 403 on this from Squid

Lets now try http access to youtube.com

[[email protected] squid]# curl -I www.youtube.com -x 192.168.0.2:3128
HTTP/1.0 200 OK
Date: Sun, 21 Jul 2013 17:25:37 GMT
Server: gwiseguy/2.0
X-Frame-Options: SAMEORIGIN
X-YouTube-Other-Cookies: VISITOR_INFO1_LIVE=A4yQlrbOatM;PREF=f1=50000000
P3P: CP="This is not a P3P policy! See http://support.google.com/accounts/bin/answer.py?answer=151657&hl=en-GB for more info."
X-Content-Type-Options: nosniff
Cache-Control: no-cache
Expires: Tue, 27 Apr 1971 19:44:06 EST
Set-Cookie: YSC=zqSQpd08t-o; path=/; domain=.youtube.com; httponly
Set-Cookie: PREF=f1=50000000; path=/; domain=.youtube.com; expires=Sat, 22-Mar-2014 05:18:37 GMT
Set-Cookie: VISITOR_INFO1_LIVE=A4yQlrbOatM; path=/; domain=.youtube.com; expires=Sat, 22-Mar-2014 05:18:36 GMT
Content-Type: text/html; charset=utf-8
X-XSS-Protection: 1; mode=block
X-Cache: MISS from box1.agrainofsalt.com
X-Cache-Lookup: MISS from box1.agrainofsalt.com:3128
Via: 1.0 box1.agrainofsalt.com (squid/3.1.10)
Connection: keep-alive

This works as expected. Lets try https to youtube.com now!

[[email protected] squid]# curl -I https://www.youtube.com/ -x 127.0.0.1:3128
HTTP/1.0 200 Connection established

curl: (60) Peer certificate cannot be authenticated with known CA certificates
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.

This has failed as we’ve not got the CA certificate in the bundle that curl uses, lets get curl to ignore the SSL certificate

[[email protected] squid]# curl -Ik https://www.youtube.com/ -x 127.0.0.1:3128
HTTP/1.0 200 Connection established

HTTP/1.0 503 Service Unavailable
Server: squid/3.1.10
Mime-Version: 1.0
Date: Sun, 21 Jul 2013 18:36:00 GMT
Content-Type: text/html
Content-Length: 3408
X-Squid-Error: ERR_CANNOT_FORWARD 0
Vary: Accept-Language
Content-Language: en
X-Cache: MISS from box1.agrainofsalt.com
X-Cache-Lookup: MISS from box1.agrainofsalt.com:3128
Via: 1.0 box1.agrainofsalt.com (squid/3.1.10)
Connection: keep-alive

Now lets just make sure that other https sites don’t work.

[[email protected] squid]# curl -Ik https://www.gmail.com/ -x 127.0.0.1:3128
HTTP/1.0 403 Forbidden
Server: squid/3.1.10
Mime-Version: 1.0
Date: Sun, 21 Jul 2013 18:36:28 GMT
Content-Type: text/html
Content-Length: 3261
X-Squid-Error: ERR_ACCESS_DENIED 0
Vary: Accept-Language
Content-Language: en
X-Cache: MISS from box1.agrainofsalt.com
X-Cache-Lookup: NONE from box1.agrainofsalt.com:3128
Via: 1.0 box1.agrainofsalt.com (squid/3.1.10)
Connection: keep-alive

curl: (56) Received HTTP code 403 from proxy after CONNECT

 Forwarding all traffic via the Proxy server

Now the way that this is done depends on the firewall or router in use. What we need to achieve is to either D-NAT or redirect all traffic on port 80 / 443 outbound to the Squid server.

For a Cisco ASA there is a guide on how to do this with WCCP

For a Linux based device you would want to have a IPTables rule similar to

iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 80 -j DNAT --to 192.168.0.2:3128 -s ! 192.168.0.2
iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 443 -j DNAT --to 192.168.0.2:3128 -s ! 192.168.0.2

 

Categories
Linux

Creating a CA using OpenSSL – with OCSP

SSL Certificates are a source of huge amounts of confusion. There are two things that a SSL session will provide. The first is encryption, which can be provided with “self signed” certificates. The second, and arguably the more important is authentication of the remote server. This is managed by “Certification Authorities”. Web Browsers will have a set of known CAs that are trusted, and any certificate signed by them is therefore also trusted. Obviously if a CA has had a security breach then all bets are off.

Within an organisation it is usually preferable for NON PUBLIC facing sites and services to use ‘self signed’ or internal CA signed certificates. The later is usually more sensible, however it comes with the issue of more administrative time is required, and also that all clients must trust this CA.

There are various different ways of creating a CA, Windows Server 2003 and above come with their own CA software, and most UNIX/Linux distributions have OpenSSL available.

In this guide I’m going to walk through the creation of a CA using OpenSSL. I’m also going to look at enabling additional features such as OSCP (a way of clients confirming if a certificate is still valid) and go over how to create “Server Alternative Name” certificates (also known as UC or SAN certs, allowing multiple hostnames/domainnames to exist on the same cert).

One key thing to remember here is security of the CA. You must ensure that no unauthorized access is permitted to the CA, as if someone has been able to gain this, they will have access to issue certificates.

I’m also going to ensure that we setup OCSP, which is a way of clients checking to see that certificates are still valid and not revoked.

Prerequisites

Before we start we need to have the following:

  • A Linux Server with openssl installed (for this example I’m going to be using CentOS 6.4, however any linux distribution should work)
  • A Domain name (in this example I’m going to use test.local)

Configure OpenSSL

On a CentOS/RedHat system there is already a basic openssl.cnf file created, that the scripts for managing a CA already take into account. /etc/pki/tls/openssl.cnf

Open this up in which ever editor you like and do the following:

  • Locate countryName_default = XX and change the XX to which ever country code you are in, for example the United Kingdom would be GB
  • Locate #stateOrProvinceName_default = Default Province and edit this line so there is no # at the start, and that Default Province now is set to our State/Proviince/County/City
  • Locate localityName_default = Default City and edit this to be your City
  • Locate 0.organizationName_default  and edit this to be your City

At this point we’ve edited the config so that for any new requests you won’t have to type these in!

Whilst still in the Text Editor we need to setup the OCSP side of things.

  • Locate the [ usr_cert ] section and add 
    authorityInfoAccess = OCSP;URI:http://URL_TO_SERVER_THAT_WILL_HOST_OCSP:8888

    In this example I’m going to put this on the CA, but this is *NOT* a good idea from a security perspective. You want the CA to have as little (if indeed any) access from the outside.

  • We also need to create the OCSP ‘extensions’ section. Add this to the end of the file
    [ v3_OCSP ]
    basicConstraints = CA:FALSE
    keyUsage = nonRepudiation, digitalSignature, keyEncipherment
    extendedKeyUsage = OCSPSigning

     

Create the CA

We’re going to use the OpenSSL CA script to do this.

  • Change directory to /etc/pki/tls/misc 
  • Run the CA command: ./CA -newca 
  • Whilst Running it you will be asked
              • File name : Just hit enter here
              • PEM Passphrase  : this is the password you will use for the CA. Make sure it’s secure!
              • Country Name : Hit enter here
              • State or Province Name : Hit enter here
              • Locality Name (eg, city) : Hit enter here
              • Organization Name (eg, company) : Hit enter here
              • Organizational Unit Name : Hit enter here
              • Common Name (eg, your name or your server’s hostname) : For this its generally considered best to set this to ca.domain, so in this case ca.test.local
              • Email Address : Hit enter here
              • A challenge password : Hit Enter here
              • An optional company name : Hit enter here
              • Enter pass phrase for /etc/pki/CA/private/./cakey.pem :: Enter the CA password here

The end output should look similar to

[[email protected] misc]# ./CA -newca
CA certificate filename (or enter to create)

Making CA certificate ...
Generating a 2048 bit RSA private key
......................................................................+++
.......+++
writing new private key to '/etc/pki/CA/private/./cakey.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [GB]:
State or Province Name (full name) [London]:
Locality Name (eg, city) [London]:
Organization Name (eg, company) [AGrainOfSalt]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:ca.test.local
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /etc/pki/tls/openssl.cnf
Enter pass phrase for /etc/pki/CA/private/./cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number:
            c5:07:3c:dc:c5:8a:cb:ab
        Validity
            Not Before: Jul 21 09:37:18 2013 GMT
            Not After : Jul 20 09:37:18 2016 GMT
        Subject:
            countryName               = GB
            stateOrProvinceName       = London
            organizationName          = AGrainOfSalt
            commonName                = ca.test.local
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                1F:F8:DB:5F:7B:FE:30:29:6F:E2:E2:C8:23:DE:5B:77:AE:82:2D:F8
            X509v3 Authority Key Identifier:
                keyid:1F:F8:DB:5F:7B:FE:30:29:6F:E2:E2:C8:23:DE:5B:77:AE:82:2D:F8

            X509v3 Basic Constraints:
                CA:TRUE
Certificate is to be certified until Jul 20 09:37:18 2016 GMT (1095 days)

Write out database with 1 new entries
Data Base Updated
[[email protected] misc]#

 

At this point you have a CA setup and ready to go. You will need to ensure that the CA public certificate is installed on the browsers / devices that you will be using. This can be downloaded using a SCP client from /etc/pki/CA/cacert.pem

Creating a OCSP signing certificate

In order to host an OCSP server, we have to generate a OCSP signing certificate. If you’re going to have multiple OCSP servers, you may want to have multiple certificates.

We’re going to create a directory, and a request for the certificate

cd /etc/pki/CA
mkdir OCSP
cd OCSP
openssl req -new -nodes -out ocsp.test.local.csr -keyout ocsp.test.local.key -extensions v3_OCSP

At this point we now need to sign the request and make the certificate

 openssl ca -in ocsp.test.local.csr -out ocsp.test.local.crt -extensions v3_OCSP

You will be asked for

  • CA Passphrase
  • Sign the certificate? [y/n]: Say yes to this
  • 1 out of 1 certificate requests certified, commit? Say yes to this as well

Start OCSP server

At this point we now also need to run the OCSP server. Be aware that this is going to run as root in this example, which you should *NOT* do. You will want to ensure permissions are done in a way that a normal user, I’m not going to cover this at the moment though. Start the server with the following

openssl ocsp -index /etc/pki/CA/index.txt -port 8888 -rsigner /etc/pki/CA/OCSP/ocsp.test.local.crt -rkey /etc/pki/CA/OCSP/ocsp.test.local.key -CA /etc/pki/CA/cacert.pem -text -out /etc/pki/CA/OCSP/log.txt &

 

 Issuing a Certificate

Now that you’ve got a working CA, you can sign any certificate requests. There are multiple ways of creating these, some software will provide you a CSR, but in this example I’m going to do this all on the CA its self (don’t do this in production!)

  • Change directory to /etc/pki/tls/misc
  • Run the CA command: ./CA -newreq

This will give a result similar to below

Generating a 2048 bit RSA private key
...................................+++
.........................+++
writing new private key to 'newkey.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [GB]:
State or Province Name (full name) []:London
Locality Name (eg, city) [London]:
Organization Name (eg, company) [AGrainOfSalt]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:web1.test.local
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Request is in newreq.pem, private key is in newkey.pem

We now need to sign the certificate

  • Run the CA command 
    ./CA -sign

This will give a result similar to

[[email protected] misc]# ./CA -sign
Using configuration from /etc/pki/tls/openssl.cnf
Enter pass phrase for /etc/pki/CA/private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number:
            c5:07:3c:dc:c5:8a:cb:ad
        Validity
            Not Before: Jul 21 13:02:27 2013 GMT
            Not After : Jul 21 13:02:27 2014 GMT
        Subject:
            countryName               = GB
            stateOrProvinceName       = London
            localityName              = London
            organizationName          = AGrainOfSalt
            commonName                = web1.test.local
        X509v3 extensions:
            Authority Information Access:
                OCSP - URI:http://162.13.47.187:8888

            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                60:06:C1:47:5B:DE:6F:0C:64:00:DA:A9:77:05:67:AA:8F:39:C9:AF
            X509v3 Authority Key Identifier:
                keyid:1F:F8:DB:5F:7B:FE:30:29:6F:E2:E2:C8:23:DE:5B:77:AE:82:2D:F8

Certificate is to be certified until Jul 21 13:02:27 2014 GMT (365 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            c5:07:3c:dc:c5:8a:cb:ad
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=GB, ST=London, O=AGrainOfSalt, CN=ca.test.local
        Validity
            Not Before: Jul 21 13:02:27 2013 GMT
            Not After : Jul 21 13:02:27 2014 GMT
        Subject: C=GB, ST=London, L=London, O=AGrainOfSalt, CN=web1.test.local
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:97:d0:a4:0e:c3:61:c0:b0:8e:af:5b:2a:96:85:
                    fc:e8:e9:23:3c:97:f0:2f:15:5e:a3:00:49:0c:b6:
                    2d:5a:2c:f0:ff:ca:2c:49:f1:ee:d8:3a:0b:f2:ab:
                    9b:96:f8:a2:cf:a2:6a:82:63:3b:7a:9b:7c:b1:4c:
                    4a:65:c8:70:cc:7c:90:1b:7b:b3:a0:6c:91:5d:1e:
                    12:93:31:d0:68:bb:33:6e:e7:54:91:fc:f8:e1:b3:
                    3e:26:33:4c:d0:d7:ea:fd:6f:1f:b6:a4:cf:1b:82:
                    03:41:58:d5:47:4d:f6:a3:50:a5:4e:92:74:96:c6:
                    1f:b2:3d:33:00:25:62:35:2b:89:6e:60:37:d0:44:
                    d4:11:89:0d:21:ed:3f:d3:54:db:c5:21:5f:43:3f:
                    bd:2b:e6:a9:48:f1:dd:11:0f:a2:f2:d9:7a:2f:0b:
                    78:8c:98:b2:3a:4b:23:fb:16:41:9e:b8:69:ee:e5:
                    22:bc:67:49:40:fe:eb:13:d6:45:50:3b:cc:14:b3:
                    1b:ba:e1:5d:89:33:ed:8e:6a:05:36:0e:c2:bb:21:
                    9f:6f:6b:17:99:a2:53:cc:69:24:03:95:db:89:79:
                    46:8d:05:ed:1d:b6:c3:22:89:9a:43:e5:ff:c1:b7:
                    58:f1:40:ab:b1:e5:ca:c1:ec:64:59:a7:fb:53:44:
                    8e:27
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            Authority Information Access:
                OCSP - URI:http://162.13.47.187:8888

            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                60:06:C1:47:5B:DE:6F:0C:64:00:DA:A9:77:05:67:AA:8F:39:C9:AF
            X509v3 Authority Key Identifier:
                keyid:1F:F8:DB:5F:7B:FE:30:29:6F:E2:E2:C8:23:DE:5B:77:AE:82:2D:F8

    Signature Algorithm: sha1WithRSAEncryption
        88:05:46:ab:a5:50:08:56:50:ca:4b:15:af:1e:84:ab:b1:d0:
        b0:b9:81:52:0b:f5:e6:28:51:71:a6:11:64:46:04:42:84:eb:
        84:5f:d1:87:64:18:60:1b:31:7a:13:b2:9d:10:bd:56:7a:7f:
        2e:88:23:55:52:a4:a2:9d:d0:8c:70:b7:0a:69:50:96:fa:54:
        be:6b:bd:24:25:9d:59:52:30:33:92:cc:63:3e:5c:47:87:e3:
        ca:d0:55:09:c3:2a:4b:fc:f0:b8:34:3f:1a:d3:b9:3a:66:7f:
        86:d1:8c:08:4c:cf:19:3d:c5:c7:3f:b1:73:7b:bd:54:73:c6:
        65:74:8e:8a:17:5a:e9:d9:bd:91:39:8b:ae:46:10:52:d9:03:
        db:51:3a:14:41:2b:96:6c:ea:db:c7:20:89:48:ae:32:fe:05:
        66:2b:5c:48:19:7b:b8:45:99:7a:b1:45:b0:66:06:31:3d:86:
        c5:c3:7b:99:d5:cf:1f:9d:64:69:bf:60:1a:d8:03:7e:75:e2:
        44:b7:41:36:aa:b8:c0:df:9c:24:74:eb:ab:b6:b3:1b:74:be:
        73:bf:52:bd:b7:de:31:81:ff:df:b6:f4:b9:8f:9f:22:93:3b:
        12:5c:a4:6a:3f:aa:8e:8a:7c:69:65:e9:65:f7:98:44:1b:59:
        7d:e4:ca:e0
-----BEGIN CERTIFICATE-----
MIID5DCCAsygAwIBAgIJAMUHPNzFisutMA0GCSqGSIb3DQEBBQUAME0xCzAJBgNV
BAYTAkdCMQ8wDQYDVQQIDAZMb25kb24xFTATBgNVBAoMDEFHcmFpbk9mU2FsdDEW
MBQGA1UEAwwNY2EudGVzdC5sb2NhbDAeFw0xMzA3MjExMzAyMjdaFw0xNDA3MjEx
MzAyMjdaMGAxCzAJBgNVBAYTAkdCMQ8wDQYDVQQIDAZMb25kb24xDzANBgNVBAcM
BkxvbmRvbjEVMBMGA1UECgwMQUdyYWluT2ZTYWx0MRgwFgYDVQQDDA93ZWIxLnRl
c3QubG9jYWwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCX0KQOw2HA
sI6vWyqWhfzo6SM8l/AvFV6jAEkMti1aLPD/yixJ8e7YOgvyq5uW+KLPomqCYzt6
m3yxTEplyHDMfJAbe7OgbJFdHhKTMdBouzNu51SR/Pjhsz4mM0zQ1+r9bx+2pM8b
ggNBWNVHTfajUKVOknSWxh+yPTMAJWI1K4luYDfQRNQRiQ0h7T/TVNvFIV9DP70r
5qlI8d0RD6Ly2XovC3iMmLI6SyP7FkGeuGnu5SK8Z0lA/usT1kVQO8wUsxu64V2J
M+2OagU2DsK7IZ9vaxeZolPMaSQDlduJeUaNBe0dtsMiiZpD5f/Bt1jxQKux5crB
7GRZp/tTRI4nAgMBAAGjgbMwgbAwNQYIKwYBBQUHAQEEKTAnMCUGCCsGAQUFBzAB
hhlodHRwOi8vMTYyLjEzLjQ3LjE4Nzo4ODg4MAkGA1UdEwQCMAAwLAYJYIZIAYb4
QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBRg
BsFHW95vDGQA2ql3BWeqjznJrzAfBgNVHSMEGDAWgBQf+Ntfe/4wKW/i4sgj3lt3
roIt+DANBgkqhkiG9w0BAQUFAAOCAQEAiAVGq6VQCFZQyksVrx6Eq7HQsLmBUgv1
5ihRcaYRZEYEQoTrhF/Rh2QYYBsxehOynRC9Vnp/LogjVVKkop3QjHC3CmlQlvpU
vmu9JCWdWVIwM5LMYz5cR4fjytBVCcMqS/zwuDQ/GtO5OmZ/htGMCEzPGT3Fxz+x
c3u9VHPGZXSOihda6dm9kTmLrkYQUtkD21E6FEErlmzq28cgiUiuMv4FZitcSBl7
uEWZerFFsGYGMT2GxcN7mdXPH51kab9gGtgDfnXiRLdBNqq4wN+cJHTrq7azG3S+
c79SvbfeMYH/37b0uY+fIpM7Elykaj+qjop8aWXpZfeYRBtZfeTK4A==
-----END CERTIFICATE-----
Signed certificate is in newcert.pem

The certificate now exists and can be seen in newcert.pem (and the key in newkey.pem)

Checking OCSP status

We can now check to see if the above certificate is valid via OCSP:

openssl ocsp -CAfile /etc/pki/CA/cacert.pem -issuer /etc/pki/CA/cacert.pem -cert newcert.pem -url http://127.0.0.1:8888 -resp_text

This will return an address similar to below:

[[email protected] misc]# openssl ocsp -CAfile /etc/pki/CA/cacert.pem -issuer /etc/pki/CA/cacert.pem -cert newcert.pem -url http://127.0.0.1:8888 -resp_text
OCSP Response Data:
    OCSP Response Status: successful (0x0)
    Response Type: Basic OCSP Response
    Version: 1 (0x0)
    Responder Id: C = GB, ST = London, O = AGrainOfSalt, CN = ocsp.test.local
    Produced At: Jul 21 13:06:37 2013 GMT
    Responses:
    Certificate ID:
      Hash Algorithm: sha1
      Issuer Name Hash: CD84AAE91120F3595F8B572F367D17BBD2B7D51E
      Issuer Key Hash: 1FF8DB5F7BFE30296FE2E2C823DE5B77AE822DF8
      Serial Number: C5073CDCC58ACBAD
    Cert Status: good
    This Update: Jul 21 13:06:37 2013 GMT

    Response Extensions:
        OCSP Nonce:
            04108CFBA6175ED9F3E58C50C39889E2B484
    Signature Algorithm: sha1WithRSAEncryption
        ba:2e:74:c5:3a:57:88:f1:7a:0f:d4:e9:01:f0:7c:31:2e:a3:
        31:cb:25:c4:8a:91:e6:05:88:39:3a:18:ef:89:eb:02:6a:46:
        12:4e:12:90:85:55:3d:22:67:aa:68:ab:11:08:d9:89:29:20:
        b6:36:78:89:3d:5d:c5:9b:7a:94:1a:e4:4f:48:b2:45:53:0b:
        86:65:fb:64:cc:e0:15:a6:32:7a:2d:00:c1:a6:c7:25:c1:a0:
        f8:4b:67:42:77:ad:cf:ab:01:8a:0c:3a:65:18:3f:d7:85:26:
        6c:a4:d0:ab:8c:40:2e:2f:f7:3f:0f:9d:f7:6c:80:d8:52:0e:
        8b:21:5d:3c:cb:d9:6b:c3:87:05:eb:00:4d:6a:b8:74:d5:28:
        fb:08:63:4a:b4:4b:c8:67:c9:01:f7:51:75:6e:50:15:bd:db:
        a9:cc:83:26:63:67:ce:2b:96:d6:e2:e8:df:01:82:36:75:23:
        44:30:d9:8e:32:a9:74:ce:69:4c:f3:79:80:a5:73:75:b3:bf:
        c2:b4:66:e8:70:b7:4c:9c:4a:3d:2a:ff:98:25:d2:19:86:3b:
        70:78:e0:7c:72:82:69:e0:08:6e:1d:a5:e8:d2:6f:4d:e7:a5:
        a2:15:05:5f:98:b5:1e:20:13:54:e2:e2:62:4d:38:5d:e8:b1:
        56:15:97:00
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            c5:07:3c:dc:c5:8a:cb:ac
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=GB, ST=London, O=AGrainOfSalt, CN=ca.test.local
        Validity
            Not Before: Jul 21 10:16:20 2013 GMT
            Not After : Jul 21 10:16:20 2014 GMT
        Subject: C=GB, ST=London, O=AGrainOfSalt, CN=ocsp.test.local
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:f2:1e:67:ef:42:45:2c:3f:ed:09:c6:d2:11:ca:
                    28:ce:16:ac:2b:15:7a:25:34:dc:35:2d:d9:6e:60:
                    b6:06:ed:ea:fc:ec:0e:37:0f:44:bc:25:02:b6:41:
                    a2:89:c8:58:e3:cc:0d:c4:b6:b1:e3:08:b0:2d:6c:
                    85:52:0a:3a:4c:ae:ad:1b:8a:d7:0b:fd:da:f7:85:
                    94:66:e9:25:48:a3:d6:07:27:e6:51:ee:03:96:db:
                    80:ec:60:00:27:ac:8f:93:63:e6:8a:22:d9:45:da:
                    8a:93:67:aa:d8:6a:00:32:0c:8c:84:87:47:30:a2:
                    96:21:44:e1:cd:19:a9:bb:0e:9a:70:5b:fc:4e:a0:
                    79:ca:27:b0:5f:c0:7c:3d:23:c7:ae:26:c2:20:86:
                    97:89:f6:a9:32:0e:e9:10:c1:c0:f3:51:4e:61:a7:
                    6c:ea:84:d2:d2:7d:ec:6d:58:f8:5c:c8:4e:37:f1:
                    05:03:52:07:fc:96:dd:69:8b:6e:30:d9:75:0a:4c:
                    17:74:89:4c:bc:06:b0:d9:d3:03:a3:bd:75:c5:9a:
                    2c:7b:75:f8:6f:e4:44:a9:ef:08:49:aa:88:49:1a:
                    41:d7:98:8e:8f:ac:be:bb:e1:66:e0:33:05:2d:64:
                    7e:90:fc:62:eb:bc:18:45:7d:cb:23:bb:af:3c:2c:
                    0b:a1
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            X509v3 Key Usage:
                Digital Signature, Non Repudiation, Key Encipherment
            X509v3 Extended Key Usage:
                OCSP Signing
    Signature Algorithm: sha1WithRSAEncryption
        92:e0:49:92:23:63:fe:04:8d:5d:cf:79:fb:60:b6:3d:63:6c:
        43:8d:5a:95:09:ae:c0:75:ea:c3:08:9e:f1:1e:f3:bf:34:c4:
        f2:d7:93:58:55:b4:c5:3a:16:48:76:d8:04:b3:dc:69:67:ce:
        e3:16:6a:e9:47:06:33:16:9e:aa:e2:99:49:74:9b:2c:22:99:
        3e:5b:50:57:2b:46:da:25:d6:e7:5b:4e:36:bd:82:ac:3a:d0:
        f2:73:c0:c4:1e:27:57:63:c5:fb:0c:19:86:2b:45:dc:cb:f1:
        b5:9c:fa:22:da:d9:0c:e4:e0:5a:53:87:e1:6e:d9:7b:d9:7d:
        cf:33:90:66:07:b3:9a:38:81:63:6c:c8:7f:a4:d2:8c:15:23:
        68:18:4a:ee:e4:61:b4:2d:29:43:75:8d:67:8a:08:55:30:e9:
        09:77:cc:24:71:1c:66:fe:77:25:28:89:f5:80:a2:7f:2d:be:
        81:22:51:33:c4:67:b9:67:1e:51:81:93:da:d7:f5:b4:80:fb:
        07:8d:c8:64:a2:98:9a:4c:55:97:88:6a:51:30:2c:2d:ba:ed:
        90:ec:bf:24:18:b0:17:c9:ae:95:85:8d:22:6b:b3:5f:9b:57:
        b7:96:38:ab:0f:75:6b:47:57:56:24:d5:01:59:87:4f:76:e6:
        f5:72:97:12
-----BEGIN CERTIFICATE-----
MIIDTjCCAjagAwIBAgIJAMUHPNzFisusMA0GCSqGSIb3DQEBBQUAME0xCzAJBgNV
BAYTAkdCMQ8wDQYDVQQIDAZMb25kb24xFTATBgNVBAoMDEFHcmFpbk9mU2FsdDEW
MBQGA1UEAwwNY2EudGVzdC5sb2NhbDAeFw0xMzA3MjExMDE2MjBaFw0xNDA3MjEx
MDE2MjBaME8xCzAJBgNVBAYTAkdCMQ8wDQYDVQQIDAZMb25kb24xFTATBgNVBAoM
DEFHcmFpbk9mU2FsdDEYMBYGA1UEAwwPb2NzcC50ZXN0LmxvY2FsMIIBIjANBgkq
hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8h5n70JFLD/tCcbSEcoozhasKxV6JTTc
NS3ZbmC2Bu3q/OwONw9EvCUCtkGiichY48wNxLax4wiwLWyFUgo6TK6tG4rXC/3a
94WUZuklSKPWByfmUe4DltuA7GAAJ6yPk2PmiiLZRdqKk2eq2GoAMgyMhIdHMKKW
IUThzRmpuw6acFv8TqB5yiewX8B8PSPHribCIIaXifapMg7pEMHA81FOYads6oTS
0n3sbVj4XMhON/EFA1IH/JbdaYtuMNl1CkwXdIlMvAaw2dMDo711xZose3X4b+RE
qe8ISaqISRpB15iOj6y+u+Fm4DMFLWR+kPxi67wYRX3LI7uvPCwLoQIDAQABoy8w
LTAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DATBgNVHSUEDDAKBggrBgEFBQcDCTAN
BgkqhkiG9w0BAQUFAAOCAQEAkuBJkiNj/gSNXc95+2C2PWNsQ41alQmuwHXqwwie
8R7zvzTE8teTWFW0xToWSHbYBLPcaWfO4xZq6UcGMxaequKZSXSbLCKZPltQVytG
2iXW51tONr2CrDrQ8nPAxB4nV2PF+wwZhitF3MvxtZz6ItrZDOTgWlOH4W7Ze9l9
zzOQZgezmjiBY2zIf6TSjBUjaBhK7uRhtC0pQ3WNZ4oIVTDpCXfMJHEcZv53JSiJ
9YCify2+gSJRM8RnuWceUYGT2tf1tID7B43IZKKYmkxVl4hqUTAsLbrtkOy/JBiw
F8mulYWNImuzX5tXt5Y4qw91a0dXViTVAVmHT3bm9XKXEg==
-----END CERTIFICATE-----
Response verify OK
newcert.pem: good
        This Update: Jul 21 13:06:37 2013 GMT

 Revoking a certificate.

Oh no! The certificate above has been compromised. We need to revoke it. This isn’t as difficult as you may think. We have a copy of all of the certificates on the CA. If we look at the certificate serial number (c5:07:3c:dc:c5:8a:cb:ad in this case) this file should exist in /etc/pki/CA/newcerts/ To revoke you need to

  • Revoke the certificate openssl ca -revoke /etc/pki/CA/newcerts/C5073CDCC58ACBAD.pem 
  • Verify that the certifcate is revoked openssl ocsp -CAfile /etc/pki/CA/cacert.pem -issuer /etc/pki/CA/cacert.pem -cert /etc/pki/CA/newcerts/C5073CDCC58ACBAD.pem -url http://127.0.0.1:8888 -resp_text

 

Categories
Hardware Linux Software

RouterBoard as a Home Router – 4 1/2 years on

A while back I mentioned a follow up to an old blog post about the RouterBoard that i’d recently purchased and setup for home use. This is a very belated update on that board.

My requirements have since changed from the original post, but not dramatically so. The requirement for LACP has disapeared, IPSec is no longer used, but a requirement for Dynamic Routing has appeared.

All in all, I have to say that I still cannot recommend RouterOS enough. I’ve been using it the past 4 1/2 years, and have recommended a large number of folks to use it.

The main reason behind this is that it just works, there’s not really any faffing about that needs to be done, and if you’re running the stable release, everything does just work.

Feature wise, this is right up there with some of the big brands (Cisco, Juniper et all), however its fair to say not with the same price tag.

Categories
Hardware Linux vmware

iSCSI Target re scanning on VMWare

If you’re using iSCSI on VMWare but have a requirement to rescan the luns after a machine has booted (For example a VM which has DirectPath to a Storage card enabled, which is hosting your iSCSI luns) you can simply do so with the following command

#!/bin/sh
ssh [email protected] 'esxcli storage core adapter rescan --all && esxcfg-rescan -A' 1>/dev/null 2>/dev/null
Categories
F5 iRule Linux

F5 LoadBalancing on a per app mountpoint

With some customers solutions I’ve seen a common requirement to do loadbalancing decision based on the actual application server serving the content, this obviosuly introduces a few issues if you’re using a single base URL for this

If we take the example below

www.example.com/ -> Web Servers
www.example.com/app1 -> App1 Servers
www.example.com/app2 -> App1 Servers

With this in mind, its not possible to use traditional Layer 3 / Layer 4 load balancers, and would require a L7 Load balancer, such as a F5 LTM or Riverbed Stingray (ZTM/ZXTM). I’m going to concentrate on the F5 in this example.

On the F5 you have the abbility to use a iRule to preform load balacning actions. On a Virtal Server that has the “http” profile enabled, you would be able to add a iRule similar to below.

# Name        : Application Loadbalacning Split
# Date        : 19/03/2013
# Purpose     : Split loadbalancing based on application
# Methodology : Change pool based on url

# Set the poolname prefix based on the virtual servers name.
# Pool will always be POOL_$SERVERPOOL
when CLIENT_ACCEPTED {
    if { [virtual] contains "testing" } {
        set serverpool "testing"
    } else {
        set serverpool "liveserver"
    }
}

# Preform a load balancing decision based on the endpoint
# Split the HTTP::path out on '/' and return only the first //
# This doesn't convert from HEX / Encoded urls, but sends to default pool
when HTTP_REQUEST {
    switch [ lindex [split [string tolower [HTTP::path] ] "/" ]  1 ] {
        "app1" {
            set NEWPOOL "APP1_$serverpool"
        }
        "app2" {
            set NEWPOOL "APP2_$serverpool"
        }
        "default" {
            set NEWPOOL "default_$serverpool"
        }
    }
    pool $NEWPOOL

}

# We add a HTTP Header to identify the app pool that we're going to
when HTTP_RESPONSE {
    HTTP::header insert "X-AP" $NEWPOOL
}

There are multiple events that this will trigger.

  1. CLIENT_ACCEPTED
  2. This event is triggered whenever a new connection is made to the Load balancer. In our case the code will check to see if the virtual servers name contains “testing”, which if it does sets the serverpool variable to contain “testing”, otherwise it will set it to “liveserver”

  3. HTTP_REQUEST
  4. This event is triggered on any new HTTP Request. In our case this preforms a ‘switch’ (a multiple if/else statement) on the URL. We do however preform two “transformations” on the URL, the first is we convert it to lower case. the second is that we only take the URL between the first two /’s. So for the URL http://www.example.com/app1/test we would use app1 for teh switch statement.
    Based on the path, we will then set the NEWPOOL variable, and then set the pool to NEWPOOL

  5. HTTP_RESPONSE
  6. This event is triggered when the server send a response to a HTTP Request. We add the “X-AP” header to the response, and set this to the NEWPOOL variable.

Categories
Linux Projects Software

Yubikey and server authentication

After starting to use the Yubikey for LastPass and various other online servers I’ve started also using my yubikey for SSH access to my server(s).

I’ve touched on google_authenticator and pam_yubico for authentication in a previous post however I will be going into this in a bit more detail.

Taking a machine at home as an example. My requirements are simple

  • NO SSH Key access to be allowed – as there is no way to require a second factor with an SSH Key (Passphrases can be removed or a new key generated)
  • Access from Local machines to be allowed without Two Factor being enabled
  • Yubikey to be the Primary TFA
  • Fall back to google authenticator should either the Yubico servers be down, an issue with my keys or I just don’t have a USB port available (IE I’m on a phone or whatever)
  • In order to meet these requirements I’m going to need the following

  • yubico-pam Yubikey PAM
  • Google Authenticator PAM
  • pam_access
  • The server is running Archlinux, and luckily all of these are within AUR – and as such I’m not going to cover the install of the modules.

    In order to restrict SSHd access as above I need the following auth lines in /etc/pam.d/sshd

    # Check unix password
    auth            required        pam_unix.so try_first_pass
    # check to see if the User/IP combo is on the skip list - if so, skip the next two lines
    auth            [success=2 default=ignore] pam_access.so accessfile=/etc/security/access_yubico.conf
    # Check /etc/yubikey for the users yubikey and skip the next line if it all works
    auth            [success=1 default=ignore ]     pam_yubico.so id=1 url=https://api.yubico.com/wsapi/2.0/verify?id=%d&otp=%s authfile=/etc/yubikey
    # Check against google authenticator
    auth            required        pam_google_authenticator.so
    auth            required        pam_env.so
    

    The next step is ensure that the relevant users and IP are listed in /etc/security/access_yubico.conf

    # Allow welby from 1.2.3.4
    + : welby : 1.2.3.4
    # Deny all others
    - : ALL : ALL
    

    After this is setup we will also need to setup the yubikey file /etc/yubikey

    welby:ccccccdddddd:cccccccccccc
    

    I’m not going to cover configuration of google authenticator with the google-authenticator command

    The final changes are to the /etc/ssh/sshd_config ensuring that the following are set

    PasswordAuthentication no
    PubkeyAuthentication no
    PermitRootLogin no
    ChallengeResponseAuthentication yes
    UsePAM yes
    
    Categories
    Linux Projects

    PAM and Two Factor authentication

    As the need for Two factor authentication is a requirement for PCI-DSS (Payment Card Industry standard) and SSH Key with password is not always deemed to be an acceptable form of Two factor authorisation there is now a surge in different forms of two factor auth, all with their own pros and cons.

    For a small business or ‘Prosumer’ (professional consumers) the market incumbent (RSA) is not a viable option due to the price of the tokens and the software / appliance that is required. There are cheaper (or free!) alternatives for which two that I’ve used at Google Authenticator, and Yubikey.

    Google Authenticator is an OATH-TOTP system that much like RSA generates a one time password once every 30 seconds. It’s avaiable as an App for the Big three mobile platforms (iOS, Android and Blackberry).

    Yubikey is a hardware token that emulates a USB keyboard, that when the button is pressed, generates a one time password. This is supported by services such as lastpass.

    Both solutions have the ability to be used with their own PAM modules. Installation of either is simple, but what happens if you want to use both, but only require one of these.

    Luckily PAM makes it quite easy !

    auth            required        pam_unix.so try_first_pass
    auth            [success=1 default=ignore ]     pam_yubico.so id=1 url=https://api.yubico.com/wsapi/2.0/verify?id=%d&otp=%s
    auth            required        pam_google_authenticator.so
    

    In the above example the user must enter a password and then provide either their yubikey or their google_authenticator.

    Should the password be incorrect the user will still be prompted for their yubikey or google authenticator, but will then fail. Should they provide a password and then their yubikey, they will not be asked for their google authenticator. Should they provide password and not a yubikey, they will be prompted for their google authenticator!

    Categories
    Linux Projects Software Uncategorized

    A quick (and quite unscientific!) break down of Rackspace CloudFiles UK vs Amazon S3 (Ireland)

    (Disclaimer – I’m a Rackspace Employee, the postings on this site are my own, may be bias, and don’t necessarily represent Rackspace’s positions, strategies or opinions. These tests have been preformed independently from my employer by my self)

    As Rackspace have recently launched a ‘beta’ Cloudfiles service within the UK I thought I would run a few tests to compare it to Amazon’s S3 service running from Eire (or Southern Ireland).

    I took a set of files, totalling 18.7GB, with file sizes ranging from between 1kb and 25MB, text files, and contents being mainly Photos (both JPEG and RAW (cannon and nikon), plain text files, GZiped Tarballs and a few Microsoft Word documents just for good measure.

    The following python scripts were used:

    Cloud Files
    Upload

    import cloudfiles
    import sys,os
    
    api_username="USERNAME"
    api_key="KEY"
    auth_url="https://lon.auth.api.rackspacecloud.com/v1.0"
    dest_container="CONTAINER"
    local_file_list = sys.stdin.readlines()
    cf = cloudfiles.get_connection(api_username, api_key, authurl=auth_url)
    containers = cf.get_all_containers()
    for container in containers:
        if container.name == dest_container:
                backup_container = container
    
    def upload_cf(local_file):
        u = backup_container.create_object(local_file)
        u.load_from_filename(local_file)
    
    for local_file in local_file_list:
            local_file = local_file.rstrip()
            local_file_size = os.stat(local_file).st_size/1024
            print "uploading %s (%dK)" % (local_file, local_file_size)
            upload_cf(local_file)
    

    Download

    api_username="USERNAME"
    api_key="KEY"
    auth_url="https://lon.auth.api.rackspacecloud.com/v1.0"
    dest_container="CONTAINER"
    
    
    import cloudfiles
    import sys,os
    
    #Setup the connection
    cf = cloudfiles.get_connection(api_username, api_key, authurl=auth_url)
    
    #Get a list of containers
    containers = cf.get_all_containers()
    
    # Lets setup the container
    for container in containers:
        if container.name == dest_container:
                backup_container = container
    
    #Create the container if it does not exsit
    try:
        backup_container
    except NameError:
        backup_container = cf.create_container(dest_container)
    
    # We've now got our container, lets get a file list
    def build_remote_file_list(container):
        remote_file_list = container.list_objects_info()
        for remote_file in remote_file_list:
            f = open(remote_file['name'],'w')
            rf = container.get_object(remote_file['name'])
            print remote_file['name']
            for chunk in rf.stream():
                f.write(chunk)
            f.close()
    remote_file_list = build_remote_file_list(backup_container)
    

    s3
    Upload

    from boto.s3.connection import S3Connection
    from boto.s3.key import Key
    import sys,os
    
    dest_container = "CONTAINER"
    
    s3 = S3Connection('api','api_secret')
    
    buckets = s3.get_all_buckets()
    
    for container in buckets:
        if container.name == dest_container:
                    backup_container = container
    
    def build_remote_file_list(container):
        remote_file_list = container.list()
        for remote_file in remote_file_list:
            print remote_file
            f = open(remote_file,'w')
            rf = container.get_key(remote_file)
            #print remote_file['name'
            rf.get_file(f)
            f.close()
    
    local_file_list = sys.stdin.readlines()
    
    def upload_s3(local_file):
        k = Key(backup_container)
        k.key = local_file
        k.set_contents_from_filename(local_file)
    
    for local_file in local_file_list:
            local_file = local_file.rstrip()
            local_file_size = os.stat(local_file).st_size/1024
            print "uploading %s (%dK)" % (local_file, local_file_size)
            upload_s3(local_file)
    

    Download

    from boto.s3.connection import S3Connection
    from boto.s3.key import Key
    import sys,os
    
    dest_container = "CONTAINER"
    
    s3 = S3Connection('api','apt_secret')
    
    buckets = s3.get_all_buckets()
    
    for container in buckets:
        if container.name == dest_container:
                    backup_container = container
    
    def build_remote_file_list(container):
        remote_file_list = container.list()
        for remote_file in remote_file_list:
            print remote_file.name
            f = open(remote_file.name,'w')
            rf = container.get_key(remote_file.name)
            #print remote_file['name'
            rf.get_file(f)
            f.close()
    
    
    remote_file_list = build_remote_file_list(backup_container)
    
    

    The test was preformed from a Linux host which has a 100MBit connection (Uncapped/unthrottled) in London, however the test was also preformed with almost identical results from a machine in Paris (also 100mbit). Tests were also run from other locations (Dallas Fort Worth – Texas, my home ISP (bethere.co.uk)) however these locations were limited to 25mbit and 24mbit , and both reached their maximum speeds. The tests were as follows:

  • Download files from Rackspace Cloudfiles UK (these had been uploaded previously) – This is downloaded directly via the API, NOT via a CDN
  • Upload the same files to S3 Ireland
  • Upload the same files to a new “container” at Rackspace Cloudfiles UK
  • Download the files from S3 Ireland – This is downloaded directly via the API, NOT via a CDN
  • The average speeds for the tests are as follows:
    Cloudfiles
    Download: 90Mbit/s
    Upload: 85MBit/s
    S3 Ireland
    Download: ~40Mbit/s
    Upload : 13Mbit/s

    Observations

  • Cloud files seems to be able to max out a 100mbit connection for both File
  • S3 seems to have a cap of 13mbit for inbound file transfers?
  • S3 seems to either be extremely unpredictable on file transfer speeds for downloading files via the API, or there is some form of cap after a certain amount of data transferred, or there was congestion on the AWS network
  • Below is a graph showing the different connection speeds achieved using CF & S3

    As mentioned before this is a very unscientific test (and I’d say that these results have not been replicated from as many locations or as many times as I’d like to, so I would take them with a pinch of salt) , but it does appear that Rackspace cloudfiles UK is noticeably faster than S3 Ireland

    Categories
    Apple iPhone Linux

    IRSSI Prowl Notifications

    A quick script to send notifications from IRSSI for privmessages and also for highlights, I’ll put more commentary on later, but for now..

    use strict;
    use vars qw($VERSION %IRSSI);
    use Irssi;
    use LWP::UserAgent;
    
    $VERSION = '0.1';
    
    %IRSSI = (
            authors => 'Welby McRoberts',
            contact => '[email protected]',
            name => 'irssi_prowler',
            description => 'Sends a notification to Prowl to alert an iPhone of a new highlighted message',
            url => 'http://www.whmcr.com/2009/07/irssi-prowl-notifications',
            changes => 'Friday, 10 Jun 2009'
    );
    
    ######## Config
    my($PRIV_PRI, $PRIV_EVENT, $HI_PRI, $HI_EVENT, $APP, $UA, $APIKEY);
    $PRIV_PRI = 2;
    $PRIV_EVENT = 'Private Message';
    $HI_PRI = 1;
    $HI_EVENT = 'Highlight';
    $APP = 'irssi';
    $UA = 'irssi_prowler';
    $APIKEY='7b5d817bd95911b4c049e3034dcf7a96dfa3fb53';
    ########
    
    ####### Highlights
    
    sub highlight {
            my ($dest, $text, $stripped) = @_;
            if ($dest->{level} & MSGLEVEL_HILIGHT) {
                    print "prowl($HI_PRI, $APP, $HI_EVENT, $text)";
                    prowl($HI_PRI, $APP, $HI_EVENT, $text);
            }
    }
    
    ####### Private Messages
    
    sub priv {
            my ($server, $text, $nick, $host, $channel) = @_;
            print "prowl($PRIV_PRI, $APP, $PRIV_EVENT, $text)";
            prowl($PRIV_PRI, $APP, $PRIV_EVENT, $text);
    }
    
    ####### Prowl call
    
    sub prowl {
            my ($priority, $application, $event, $description) = @_;
            my ($request, $response, $url, $lwp);
            print 'pri: '.$priority;
            print 'app: '.$application;
            print 'event: '.$event;
            print 'description: '.$description;
    
            ######## Setting up the LWP
            $lwp = LWP::UserAgent->new;
            $lwp->agent($UA);
            # URL Encode
            $application =~ s/([^A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg;
        $event =~ s/([^A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg;
        $description =~ s/([^A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg;
            # Setup the url
            $url = sprintf("https://prowl.weks.net/publicapi/add?apikey=%s&priority=%d&application=%s&event=%s&description=%s&",
                                            $APIKEY,
                                            $priority,
                                            $application,
                                            $event,
                                            $description
                                            );
            print $url;
            $request = HTTP::Request->new(GET => $url);
            $response = $lwp->request($request);
            print $response;
    }
    
    ####### Bind "message private" to priv()
    Irssi::signal_add_last("message private", "priv");
    ####### Bind "print text" to highlights()
    Irssi::signal_add_last("print text", "highlight");
    
    Categories
    Hardware Linux Projects

    RouterBoard as a Home Router – 7 Months on – Part 1

    At the new year I decided that I was fed up with having my main Unix server acting as a Router (amongst other things) and decided to bite the bullet and get a full blown router. Here in lay a dilema. Being the fact that I’m a geek, I couldn’t settle for a “home” unhackable router. So this instantly ruled out most of the commercial available routers, baring those that run OpenWRT. Now don’t get me wrong, OpenWRT is more than capable, but I just didn’t feel like having to worry about hardware support, fighting with IPTables and getting hardware that probally wouldn’t scale. Now before anyone starts thinking “Scaling, but this is for a home connection!”, this is true. However I do sync my DSL at the full  24244 kbps Downstream, and 2550 kbps upstream (I live under 200m from the exchange according to my line attenuation, also my ISP doesn’t bandwidth cap, and allow for FastPath and similar to be enabled. Go BeThere!) . Also at the time, I was seriously considering investing in a secondary connection for additional bandwidth. This meant that I was left with a few choices

    • Build my Own. Using something like an ALIX/Sokeris and use something like FreeBSD (or something with a webgui for when I feel rather lazy, such as m0n0wall or pfsense. Both I’ve used previously with great success)
    • Cisco. Yes, the 800 pound gorrila of home. A ‘cheap’ 1800 or similar was going to set me back about £400, however this would have provided me most of what I needed.
    • RotuerBoard. These where, to me at least, relativly unknown. I originally looked at them for building my own system with them, and then discovered RouterOS came with the boards. This was an instant sale.

    After my first look at RouterOS I was basically sold. Main reasoning behind this was that it was a comercial Linux distribution, that actually worked well as a router, and shipped with both a CLI (Nortel-esq in this case) and a *shock* gui application. It also met my main criteria.

    • Support for 802.1Q. I have multiple vLANs at home so having support for dot1q was a necessity
    • Support for 802.3ad. As I have a few machines connecting via the router, I needed the throughput, as I don’t have gigabit switching LACP support was a necessity.
    • Support for Wireless. All good routers for the home (even a geeky one) need support for 802.11(a/b/g).
    • Support for SubSSIDs. Relating to the above, I didn’t want to have 7 wireless cards for my various networks
    • Support for WPA2-PSK and WPA2-EAP. I use RADIUS to authenticate all my personal stations to a central authentication system, but I don’t want to have to add guests to this, so PSK should also be supported.
    • Support for OpenVPN. I don’t like having my traffic to / from home going in the clear at all, so I needed to be able to connect via a VPN of some sort, My preference is OpenVPN for c2s vpns (s2s is still IPSEC…. which leads onto the next point)
    • Support for IPSec. I connect to various friends networks, and yet again, don’t want this sort of traffic in the clear, we made the standard IPSec (3des/md5) a while back
    • Support for “Unlimted” Firewall rules. This may sound silly, but anyone who has worked with the lowend Sonicwalls will know what I mean, only being able to put 20 rules is EXTREMELY restrictive especially with multiple vlans! (I’ve got roughly 300 rules)
    • Support for setting DHCP options. I used VMWare ESX at home for my test lab, so I require to be able to setup the DHCP server to be able to send the correct options for PXE (or gPXE) so this was a requirement
    • Quick booting. As silly as this may sound, I don’t want boot times of upwards of 30 seconds for my router.
    • Support for Bridging of interfaces with Firewall rules. This one is rather self explanatory really!
    • Support for UPnP. Lets face it, UPnP is required for any form of Voice/Video chat these days over the main IM networks (YIM/AIM/MSNIM)
    • Support for NetFlow or similar. This one is a nice to have, as I like to use flow-tools to generate a rough guess on what type of traffic is flowing through my network
    • Support for Traffic Shaping. Ah yes, the holy grail of routers. Unfortunately the likes of TC on linux requires a degree in astrophysics to get working how you’d like!
    • Easy configuration.

    After discovering (via the x86 installable and the demo units) that RouterOS would let me do all of the above, I decided to give it a whirl.