Secure SMTP between CentOS servers

Today I played a bit with SMTP/s for the sole purpose of getting encrypted communications across the board between 2 or more hosts. I have done a fair few setups before but this one comprises of 2 CentOS hosts, tic on 5.8 and tac on 6.2. In this setup, tac will be the master SMTP/s server. I am using standard CentOS repos with no added sugar. The difference between my usual setups and this one is that you never send unencrypted emails between the two servers.

Firstly, install the 2 servers, then install postfix and the tools to generate the certs yum install postfix crypto-utils mod_ssl. You can then generate the cert on the servers (i would recommend using 2048 rather than 1024 but this is your choice):

genkey --days 365 tac.frlinux.net

Then edit /etc/postfix/main.cf and add the following to your master smtp server (tac in this example), then restart the service:

smtp_tls_security_level = encrypt
smtp_sasl_security_options = noanonymous
smtpd_tls_key_file = /etc/pki/tls/private/tac.frlinux.net.key
smtpd_tls_cert_file = /etc/pki/tls/certs/tac.frlinux.net.crt
smtpd_tls_loglevel = 3
smtpd_tls_session_cache_timeout = 3600s
tls_random_source = dev:/dev/urandom
smtpd_tls_auth_only = yes
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

For some reason, CentOS 5.8 seems to be behaving differently, so I had to adjust the config to work properly:

smtp_tls_security_level = encrypt
smtp_sasl_security_options = noanonymous
smtpd_tls_key_file = /etc/pki/tls/private/tic.frlinux.net.key
smtpd_tls_cert_file = /etc/pki/tls/certs/tic.frlinux.net.cert
smtpd_tls_loglevel = 1
smtpd_tls_session_cache_timeout = 3600s
tls_random_source = dev:/dev/urandom
smtpd_use_tls=yes
smtpd_tls_auth_only = yes

So one thing to keep in mind is that using encrypt is definitely NOT recommended for internet setups, in which case may is what you want.

Time to test this, I suggest good old telnet to see what is returned. Seeing STARTTLS is a good sign.

[root@tic ~]# telnet tac 25
Trying ...
Connected to tac.
Escape character is '^]'.
220 tac.frlinux.net ESMTP Postfix
EHLO lucifer
250-tac.localdomain
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
quit
221 2.0.0 Bye
Connection closed by foreign host.

Now we can try a full mail and see what the master says. I used logwatch reports directed to root account on the master SMTP:

: initializing the server-side TLS engine
/tlsmgr[3931]: open smtpd TLS cache btree:/var/lib/postfix_scache
/tlsmgr[3931]: tlsmgr_cache_run_event: start TLS smtpd session cache cleanup
: connect from unknown[10.66.66.66]
: setting up TLS connection from unknown[10.66.66.66]
: unknown[10.66.66.66]: TLS cipher list "ALL:+RC4:@STRENGTH"
: SSL_accept:before/accept initialization
: SSL_accept:SSLv3 write server hello A
: SSL_accept:SSLv3 write key exchange A
: SSL_accept:SSLv3 write server done A
: SSL_accept:SSLv3 flush data
: SSL_accept:SSLv3 read client key exchange A
: SSL_accept:SSLv3 read finished A
: SSL_accept:SSLv3 write change cipher spec A
: SSL_accept:SSLv3 write finished A
: SSL_accept:SSLv3 flush data
: Anonymous TLS connection established : TLSv1 with cipher ADH-AES256-SHA (256/256 bits)
: D1A3C1BD9: client=unknown[10.66.66.66]
/cleanup[3934]: D1A3C1BD9: message-id=<20120521223615.4D2398DDE5@tic.frlinux.net>
/qmgr[3927]: D1A3C1BD9: from=<root@tic.frlinux.net>, size=3840, nrcpt=1 (queue active)
: disconnect from unknown[10.66.66.66]
/local[3935]: D1A3C1BD9: to=<root@tac.frlinux.net>, status=sent (delivered to mailbox)
/qmgr[3927]: D1A3C1BD9: removed

And there you are, full encrypted SMTP/S communications between two postfix hosts.

How to rescue your SGS2 from a bad download

This post is based on Cyanogenmod 9 and the samsung Galaxy S2. I also now do all my flashing under Linux using heimdall. If you do not know what that is or do not feel comfortable on the command line, you shall look elsewhere

I had fun tonight with a firmware that I downloaded and even though it flashed right, my phone got stuck in a boot loop. I considered my options as I realised that a full flash would pretty much mean to kiss my data goodbye. Recovery no longer worked, meaning that clockworkmod was unaccessible. On the upside, download mode still worked. So I decided to grab the resurrection edition of the nightly CM9. This build is supposed to be able to flash any SGS2 which is not on cm9 already. Once you get the tarfile, untar and look at all the files inside.

I then tried first to flash the kernel, unfortunately, a reboot later, it didn’t boot the device, here is the command I used:

heimdall flash --kernel zImage

After this I remembered reading on the 2500+ posts thread on the cm9 nightly about bootloaders, so I gave it a try:

heimdall flash --primary-boot boot.bin --secondary-boot Sbl.bin

And voila! My phone came back to life, I was able to access recovery and flash the previous image which I knew worked. I will post on Cyanogen 9 soon again, once I have more time.

Fuck you spamming bitches

Wow, amazed. I wrote a new entry yesterday about Cyanogenmod 9 and not later than this evening, I had 17 comments in moderation, all spams with useless sentences and web links to spamming sites. So fuck you spammers.

Samsung Galaxy SII and ICS: part II, the two towers.

I wrote a while back about the SGS II and ICS coming to it. Well a month later, things have moved quite significantly. First, Samsung announced and started deploying their final ROM based on ICS. I am saying based since the feedback is fairly bad and having tested it myself, I can report that it is slugish and not really nice. It feels like a rushed version of a beta. It of course contains touchwiz which destroys ICS’s looks, which for me is a no go.

In the Cyanogen territory, some fairly good news have come around, nightlies are now build when the changelog is big enough and I can only say that it improves over time. Latest build is really fast, video codecs now work, a newly improved stock kernel is in the works to do better than Samsung, Cyanogen also announced their take at security and many other things coming (Trebuchet).

Last, I would suggest taking a look at the CM9 discussion thread on XDA which contains all you need to know to flash the device. Keep in mind this is experimental, so take a look at the FAQ before coming back crying, and yes, there are issues (though that list decreased a lot over the last month). I would also suggest you try different modems depending on where you are and your usage, until recently LPJ worked quite nicely for me but LP6 seems to save more battery, you can find them all here. The ROM is experimental but honestly, this has now become my permanent ROM, I have no motivation/blocker to go back to CM7 (Gingerbread).

As of the date of this post, Samsung sources are still missing in action…

Samsung Galaxy SII and ICS 4.0.3

There is no denying that I am a pure geek, as such, I want to test everything even if it is alpha release. Google released Ice Cream Sandwich (4.x) in December and hackers have been working hard to provide ROMs. Samsung has leaked already a fair few testing versions and I got to say that it is running better everytime. I have been a long time Cyanogen user and mostly ran cm7 for the last 7 months. I have tried cm9 and it is looking very promising, problem is that until Samsung releases the ICS sources for the sgs2, there is little hope that most of the core functionalities will work as expected. However, this has nothing to do with cyanogen developers but mostly because of the way Samsung screws with multimedia codecs and the base framework (you can tell at this stage I am not an Android dev 🙂

So where does it leave us? Well, I have installed a custom version (read rooted/deodexed and customised in a few ways) from DarkyROM which gives me hope, as most things seem to behave as I expected. This ROM is based on the XXLPH leak. It seems that all is working as expected including the GPS (had to download gps fix and let it settle for 3mn) and now everything works.

This is going to be my daily driver for a while but that said, once Samsung releases the sources and Cyanogen is given the opportunity to fix the codecs, I will be making the switch back to my favourite ROM.

Before I forget, a nice article on how to restore your google authenticator keys to the new ROM the manual way: http://cadince.com/3-ways-to-move-google-authenticator/

That brings me to the last point, if you are using Cyanogen, they need your help.

Happy New Year 2012!

Here we go, another year passed. So a Happy New Year to you all, I thought It was time for some stats so here goes:

– 41 entries posted
– most popular articles were about my Samsung Galaxy SII and secret codes and cyanogen
– visits steadily increased from 2000 to 10000 every month throughout the year
– The top 3 visitors respectively are US, UK then France

So thanks for your support and I’ll try to post more and intersting stuff this year 🙂

Graphite and Nginx

I have been working on Graphite for a while and the one thing I didn’t like much was having to use Apache. It took some time to get it right, but I have eventually set it up to use supervisor, uwsgi and nginx. I have installed graphite 0.9.9 from sources. This setup is on a Debian stable system. First things first, a few packages to install: apt-get install python-dev libxml2-dev build-essential python-django-tagging. Then unpack carbon, whisper and graphite-web in that order and install them (default directory is /opt/graphite).

Then you need to grab uwsgi and unpack it and cd into the directory, you are now required to run this:

wget http://projects.unbit.it/downloads/uwsgi-0.9.9.2.tar.gz
tar xf uwsgi-0.9.9.2.tar.gz 
cd uwsgi-0.9.9.2
make -f Makefile.Py26 
cp uwsgi /usr/local/bin/
cp nginx/uwsgi_params /etc/nginx/

All is well in the universe, it is time to configure supervisor (apt-get install supervisor). Then create a file called /etc/supervisor/conf.d/uwsgi.conf and put that in. To restart supervisor, make sure you do a stop/start. Restart is flaky for me.

[program:uwsgi]
command=/usr/local/bin/uwsgi
  --module 'django.core.handlers.wsgi:WSGIHandler()'
  --socket 127.0.0.1:3031
  --chdir /opt/graphite/webapp
  --processes 1
  --master
  --harakiri 120
  --max-requests 5000
  --pythonpath "['/opt/graphite/webapp'] + sys.path"
directory=/opt/graphite/webapp
environment=DJANGO_SETTINGS_MODULE='graphite.settings'
user=www-data
autostart=true
autorestart=true
stdout_logfile=/var/log/nginx/uwsgi.log
redirect_stderr=true
stopsignal=QUIT

Next is to get your nginx config right, keep in mind that i use a directory within a vhost for graphite, so your config will differ if you use graphite as /, here is my full config:

server {
        listen 80;
        listen [::]:80; # use this only if using IPv6
        client_max_body_size    4M;
        server_name  graphite.frlinux.net;
        root   /var/www/stats;
        access_log  /var/log/nginx/stats.access.log;
        error_log  /var/log/nginx/stats.error.log;

        location / {
        }
       location /graphite/ {
                gzip off;
                include uwsgi_params;
                uwsgi_pass      127.0.0.1:3031;
        }
       location /content {
                alias /opt/graphite/webapp/graphite/content;
                gzip off;
                include uwsgi_params;
                uwsgi_pass      127.0.0.1:3031;
        }
       location /metrics {
                alias /opt/graphite/webapp/graphite/metrics;
                gzip off;
                include uwsgi_params;
                uwsgi_pass      127.0.0.1:3031;
        }
       location /dashboard {
                alias /opt/graphite/webapp/graphite/dashboard;
                gzip off;
                include uwsgi_params;
                uwsgi_pass      127.0.0.1:3031;
        }
       location /render {
                alias /opt/graphite/webapp/graphite/render;
                gzip off;
                include uwsgi_params;
                uwsgi_pass      127.0.0.1:3031;
        }
       location /browser {
                alias /opt/graphite/webapp/graphite/browser;
                gzip off;
                include uwsgi_params;
                uwsgi_pass      127.0.0.1:3031;
        }
       location /composer {
                alias /opt/graphite/webapp/graphite/composer;
                gzip off;
                include uwsgi_params;
                uwsgi_pass      127.0.0.1:3031;
        }
}

That’s it, point your browsers to your site like: http://site.example.com/graphite and it should be ready to show you data. Keep in mind that you have to take care of security which I am not covering in this article.

cgit on nginx

A friend of mine made me aware of a nicer web interface for git than gitweb called cgit. You will need to grab the source and compile it. I am assuming that you use /var/www/ as the root of your web server and fcgiwrap which should be configured right already. This is the missing bits for my config:

       location /cgit/ {
		index cgit.cgi;
		include fastcgi_params;
                gzip off;

               if ($uri ~ "/cgit/cgit.cgi") {
                        fastcgi_pass unix:/var/run/fcgiwrap.socket;
                }

        }

You then need to create a folder called /var/www/cgit in which you copy the cgit binary but also cgit.css and cgit.png. You then need to create a /etc/cgitrc configuration file which you will edit for your local configuration and projects. Mine looks like this:

root=/var/cache/git
repo.url=tripwire
repo.desc=Tripwire
repo.path=/var/cache/git/tripwire/.git

Restart/reload your nginx and you are ready to roll.

Quagga and BGP

I recently got reminded of Quagga which is an OpenSource router solution supporting RIP/OSPF/BGP/ISIS and can connect quite nicely with Cisco/Juniper routers. Having done a bit of work with BGP on bare metal Cisco/Juniper, I thought it could be fun to try out Quagga.

BIG FAT WARNING: This proof of concept does not include any proper router security, I suggest you read more about this before deploying this on a live setup.

The setup described here is done by using 2 Debian Squeeze VMs with all latest patches and quagga installed from apt. The topology is fairly simple, I am using 2 network interfaces, eth0 on both boxes is in bridged mode and the second is attached to the host only. My topology is:

  • VM #1: isis – eth0 – 192.168.0.50/255.255.255.0 – eth1 – 10.10.0.1/255.255.0.0
  • VM #2: osiris – eth0 – 192.168.0.52/255.255.255.0 – eth1 – 10.20.0.1/255.255.0.0

The first thing you got to do is enable IP forwarding: sysctl -w net.ipv4.ip_forward=1. Save this into /etc/sysctl.conf. Next, you need to create configuration files for quagga. Edit the first VM and add the following into /etc/quagga/Quagga.conf:

log stdout
!
password awesome_pass
enable password awesome_pass
!
router bgp 7675
 bgp router-id 192.168.0.50
 network 10.10.0.0/16 route-map v4-bgp
 neighbor 192.168.0.52 remote-as 7676
!
route-map v4-bgp permit 10
 set originator-id 192.168.0.50
 set community 7675:1 additive
 set extcommunity rt 7675:1
 set aggregator as 7676 192.168.0.52
 set as-path prepend 192.168.0.52
 set atomic-aggregate
 set metric 20
!
line vty
!

Edit /etc/quagga/zebra.conf and add the following:

hostname isis
password awesome_password
enable password awesome_password
interface eth1

Then edit /etc/quagga/daemons.conf and enable zebra and bgpd to YES. And restart the service: service quagga restart.

You can now edit your second router and add this in /etc/quagga/Quagga.conf:

log stdout
!
password awesome_pass
enable password awesome_pass
!
router bgp 7676
 bgp router-id 192.168.0.52
 network 10.20.0.0/16 route-map v4-bgp
 neighbor 192.168.0.50 remote-as 7675
!
route-map v4-bgp permit 10
 set aggregator as 7675 192.168.0.50
 set atomic-aggregate 
 set community 7676:1 additive
 set extcommunity rt 7676:1
 set metric 20
 set originator-id 192.168.0.52
!
line vty

Also edit /etc/quagga/zebra.conf and add the following:

hostname osiris
password awesome_password
enable password awesome_password
interface eth1

Then restart the router. You are now ready to test this and see what happens, from isis, I am going to take a look at osiris, for this, type vtysh to go to the router CLI.

First we check how BGP is looking, notice the second line with a next-hop of 192.168.0.52? This means we are getting routes information from the other router.

isis# sh ip bgp
BGP table version is 0, local router ID is 192.168.0.50
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale, R Removed
Origin codes: i - IGP, e - EGP, ? - incomplete
   Network          Next Hop            Metric LocPrf Weight Path
*> 10.10.0.0/16     0.0.0.0                 20         32768 i
*> 10.20.0.0/16     192.168.0.52            20             0 7676 i
Total number of prefixes 2

Second, we check the neighbours, you see a foreign host, this means they talk to each other.

isis# sh ip bgp neigh
BGP neighbor is 192.168.0.52, remote AS 7676, local AS 7675, external link
  BGP version 4, remote router ID 192.168.0.52
  BGP state = Established, up for 01:35:05
  Last read 09:31:26, hold time is 180, keepalive interval is 60 seconds
  Neighbor capabilities:
    4 Byte AS: advertised and received
    Route refresh: advertised and received(old & new)
    Address family IPv4 Unicast: advertised and received
  Message statistics:
    Inq depth is 0
    Outq depth is 0
                         Sent       Rcvd
    Opens:                  2          0
    Notifications:          0          0
    Updates:                1          1
    Keepalives:            97         96
    Route Refresh:          0          0
    Capability:             0          0
    Total:                100         97
  Minimum time between advertisement runs is 30 seconds
 For address family: IPv4 Unicast
  Community attribute sent to this neighbor(both)
  1 accepted prefixes
  Connections established 1; dropped 0
  Last reset never
Local host: 192.168.0.50, Local port: 179
Foreign host: 192.168.0.52, Foreign port: 36249
Nexthop: 192.168.0.50
BGP connection: non shared network
Read thread: on  Write thread: off

Last you can check the connection, this tells you how long they have been connected to each other. If you see Active instead of Established, this is not working properly.

# check the connection
isis# sh ip bgp sum
BGP router identifier 192.168.0.50, local AS number 7675
RIB entries 3, using 288 bytes of memory
Peers 1, using 4560 bytes of memory
Neighbor        V    AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
192.168.0.52    4  7676      98     101        0    0    0 01:36:52        1
Total number of neighbors 1

And a ping from the first router to confirm we are getting the routes.

isis# ping 10.20.0.1
PING 10.20.0.1 (10.20.0.1) 56(84) bytes of data.
64 bytes from 10.20.0.1: icmp_req=1 ttl=64 time=0.255 ms
64 bytes from 10.20.0.1: icmp_req=2 ttl=64 time=0.241 ms
64 bytes from 10.20.0.1: icmp_req=3 ttl=64 time=0.217 ms
64 bytes from 10.20.0.1: icmp_req=4 ttl=64 time=0.301 ms
^C
--- 10.20.0.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2998ms
rtt min/avg/max/mdev = 0.217/0.253/0.301/0.034 ms

This is all for now, I will add some IPv6 configuration soon.

OpenVPN on SGS2 using Cyanogen 7.1

I have toyed with this yesterday and thought I would share the experiment. I wanted to try out the OpenVPN software built-in Cyanogen for my Samsung Galaxy S2, for this I used a Debian on the other side (which uses a public IP). The first step is obviously installing OpenVPN on the server, then configuring it. Once this is installed, you can do the following steps, this will take care of symlinking the easy-rsa directory, create the server CA and create its certificates.

ln -s /usr/share/doc/openvpn/examples/easy-rsa/1.0 easy-rsa
cd easy-rsa
source ./vars 
./clean-all 
./build-ca 
./build-dh 
./build-key-server yourserver

Once this is done and you have checked there was no error in all the commands you typed, you can create your first client, still within the same directory do: ./build-key-pkcs12 cm7. In this example, cm7 is your client name.

This is the working config for my OpenVPN server, edit /etc/openvpn/server.conf. I chose TCP as a more reliable way to have my client keep the vpn connection over crappy GPRS.

proto tcp
port 8443
dev tun
ca /etc/openvpn/easy-rsa/keys/ca.crt
cert /etc/openvpn/easy-rsa/keys/yourserver.crt
key /etc/openvpn/easy-rsa/keys/yourserver.key
dh /etc/openvpn/easy-rsa/keys/dh1024.pem
ifconfig-pool-persist ipp.txt
server 192.168.6.0 255.255.255.0 
keepalive 10 120
persist-key
persist-tun
status /var/log/openvpn-status.log
verb 3
mssfix 1200 
tun-mtu 1200

Now comes the interesting bit, Cyanogen has a page on OpenVPN but they don’t really explain how to install the p12 cert you generated. You will need to copy that to the root of your sdcard, then go to Settings/Location and Security/Storage Credentials/Install from SD Card. Once you have selected the file, it will ask for the same password as used during the client cert generation, then you can select a storage password to keep it safe.

You can now set up your OpenVPN, go to Settings/Wireless & Networks/VPN Settings/Add VPN, then define the IP, name and certs, select the same cert for CA and user. Then go to advanced and make sure you change the IP Port and switch to TCP. Now the interesting part, it failed to connect until i rebooted the device. Has to be the shittiest fix ever but here goes…

Make sure you have started your OpenVPN server and check the logs for errors.