SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed

When you are using rvm and upgrade osx to Yosemite, this error may happen when you are developing for a rails app.

solutions

To solve this, the simplest solution is

1
rvm reinstall 2.2.3 --disable-binary

this will recompile ruby from scratch and it should solve the problem.

Background

In our office we got a dev server running centos. It is server grade machine with ECC ram and SAS hard drive. The problem with that it used to use by one dev. As the team is expanding, we need more dev server to test our code. Because I am familiar with SmartOS so we will use SmartOS as the hypervisor.

Preparation

Clone Disk

We need to do a clone on our hard disk. Since we only have one SAS hard drive with 1 partition, I need to plug in a external hard drive to clone the drive.

First we boot into GParted with live CD. Then we issue this command

# dd if=/dev/sda of=(external harddrive) bs=1M

Erase Disk

After the disk clone we can plug in the SmartOS live usb and format the hard drive.

Create KVM

After SmartOS installation, we now create a new KVM

/opt/new_vm.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
{
  "brand": "kvm",
  "vcpus": 1,
  "autoboot": true,
  "ram": 2048,
  "alias": "old_machine",
  "host": "old_machine",
  "resolvers": ["8.8.8.8", "8.8.4.4"],
  "disks": [
    {
      "boot": true,
      "model": "ide",
      "size": 153600
    }
  ],
  "nics": [
    {
      "nic_tag": "admin",
      "model": "e1000",
      "ip": "192.168.xx.xx",
      "gateway": "192.168.xx.1",
      "allow_ip_spoofing": true,
      "primary": true,
      "netmask": "255.255.255.0"
    }
  ]
}

Replace ip and gateway with your network settting.

Why I use allow_ip_spoofing is because my old machine got multiple static ip setup.

Create kvm by

# vmadm create < /opt/new_vm.json

You will get a uuid of the machine after this command.

Successfully created VM 226d5a1d-973e-4b4e-8158-ee33cc81e3f5

Restore old machine

Now we copy back the old machine disk image to the newly created KVM.

# dd if=(external harddrive) of=/dev/zvol/226d5a1d-973e-4b4e-8158-ee33cc81e3f5-disk0

Boot and test

After the disk copy finish, now you can boot up your vm and check if everything is working.

# vmadm boot 226d5a1d-973e-4b4e-8158-ee33cc81e3f5

Requirement

I played around with gruff today. The final result is really impressive. Especially it can visualize data from your database in the way you want.

Before you install this gem. You need to install few extra things. They are imagemagick, ghostscript. On Mac OSX you need to do

brew install imagemagick ghostscript

After installing both packages, you can run bundle install

Usage

To generate a graph you need to

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
require "gruff"
require "date"

# Create the graph object
g = Gruff::Line.new

# Set the title
g.title = "My First Graph"

# Let say we have a data hash
# The element is like {Date => Integer}

today     = Date.today
yesterday = Date.today.prev_day


data = { yesterday => 100, today => 200}

# We need to set the x-axis labels
# It need to be a Hash { 0 => "name 1", 1 => "name 2", … }
# We need to do a little bit of data transform here.
g.labels = Hash[(0...data.keys.size).zip data.keys.map{|day| day.strftime("%d %b")}] # => {0=>"07 Oct", 1=>"08 Oct"}

# Then we need to set the y-axis, we need to give it a name
g.data :Price, data.values

# Write the generated graph to a file
g.write "gruff.png"

This is the generated graph:

Generated Graph

Vagrant is great!

What is vagrant?

Vagrant provides easy to configure, reproducible, and portable work environments. In other words, It creates a VM for development.

I use vagrant to do my development in the past year. Slowly learning all the pros and cons of vagrant when using it for development. Vagrant use VirtualBox as a VM host. There is a problem about the license of the guest addition of VirtualBox. If I want to use it commercially I need to purchase a license from Oracle(USD50 for 100 end users). Problem is 100 licenses min buy.

Vagrant can use VMWare as a host

Later version of vagrant abstract the VM provider as a provider plugin. This open the possibility to support other hypervisor.

I own a Parallels Desktop 8 license

It would be great if I can use PD8 as my vagrant host. Now the dream came true. https://github.com/yshahin/vagrant-parallels. Vagrant Parallels plugin!

I tested it for almost 2 days. Everything works fine. I can do vagrant ssh vagrant up vagrant halt.

The site provide one box for you to use. The box for vagrant-paralles is a bit special. I want Ubuntu 12.04.3 LTS for one of my project. So I decided to build the box myself.

Veewee easy way to build vagrant box

Veewee is a tool for easily (and repeatedly) building custom Vagrant base boxes, KVMs, and virtual machine images.

Veewee supports parallels export 15 days ago. It got almost all the common linux distribution.

Building my own parallels box is not that easy

First, you need to install the parallels SDK for python. If you are using homebrew version of python you need to symlink the SDK separately.

ln -s /Library/Frameworks/ParallelsVirtualizationSDK.framework/Libraries/Python/2.7/prlsdkapi /usr/local/lib/python2.7/site-packages/

Then you need to create a definition for the box. I use

veewee parallels define 'ubuntu-12.04-lts' 'ubuntu-12.04.3-server-amd64'

In the definition directory edit the definitions.rb file. Remove virtualbox and vmware. We don’t need those since we are creating for PD.

Let’s build the box with

veewee parallels build 'ubuntu-12.04-lts' --workdir=/path/to/wd

Wait a while the os is installing. Here comes with a gotcha. If you get stuck in install grub-pc, you need to reboot you mac. I don’t know why but it works. I also found we cannot do unattended install of Parallels tools. After the build is complete, do not shutdown the instance. Install the tools using ssh with vagrant/vagrant login.

The last step of creating the box is

veewee parallels export 'ubuntu-1204-lts' --workdir=/path/to/wd

Vagrant up

So after importing the box, created the new Vagrantfile. We can start the vagrant box.

vagrant up --provider=paralles

Use the provider flag on the first time boot.

Everything is just like VirtualBox

The networking config in Vagrantfile seems still not support. But this plugin is only 0.0.4. We will see.

Google Webmaster verification

I deployed my blog on github. So I can’t use DNS verification. I used HTML verification. It require you to put a specific html file on your root directory.

How to add the file in Octopress

I tried to place the file in /public folder every time before I run rake deploy to deploy my blog. This method is too much trouble and sometime I will forget to do it.

To solve this problem, go to _config.yml file in Octopress.

Add this line:

include: ["googlexxxxxx.html"]

And place the googlexxxxxx.html file under source directory.

You can try to remove the whole public directory and run rake generate. You will see the google html file is also inside.

Self-doubt on my code

I have joined a local AD network company as a senior developer(who got out of college one year ago). I joined this company for more than half a year. Mainly working on cleaning the code and infrastructure. I redesign the AD selection algorithm and implement it. I have learned a lot from this practice. Geo targeting is one of the selection criteria.

I received a support ticket from our operation team last week. We have launched a new campaign targeting US internet user but we are recording HK IP address. The first thought that struck me was I messed up the implementation(some background information: my new algorithm is testing on production. There is no time for proxy shadowing or mock test. SHIP IT before test it!).

I rethink the whole logic in my head step-by-step. The truth is I don’t know what happen. Large scale production system is a beast. I still find myself clueless on other parts of the system.

I didn’t manage to figure out what happen so our team decided to checkout all the statistic we’ve got dig deeper to see what happen.

Cloudflare is caching javascript

I visited the publisher site and found out our script tag type become ‘text/rocketscript’. After some googling it is a thing called RocketLoader from Cloudflare.

This thing messes up with geo targeting for all of our ads. After some research, AdvretServe and Google Adsense are also having this problem.

Our javascript content is different per request. Cloudflare execute our javascript and save it. I know static content should use CDN to speed up things. But some ad network is not using static js. I don’t know much but at least all the 3-rd party agency we worked with are using dynamic js.

Solution (which is not really a solution)

We need to ask publisher to disable Cloudflare. Cloudflare not only affect geotargeting campaign. We later find out that it also lower the publisher total ad serve. We are still investigating what’s the issue. But we will list Cloudflare as not compatible with our network.

This post continues on the last post about Softether setup on a VPS.

Problem on SecureNAT

SecureNAT is a fairly simple way to setup Softether. You don’t need a lot of sysadmin skill and network understanding in order to get Softether up and running.

The problem is SecureNAT is a bit SLOW. I will show a comparison at the end of this article.

We can boost the performance using a local bridge.

Softether using local bridge

To start with you need Softether installed and setup. You can follow the guide on Softether on VPS

Just skip the last step “Enable the Virtual NAT”

Local bridge Setup

Network setup

VPN Server IP: 192.168.7.1

VPN Client IP Range: 192.168.7.50-192.168.7.60

Tap Device name: tap_soft

From here we go to the “Local Bridge Setting”

Local Bridge Setting

First we choose the Virtual Hub. It should be only one for normal setup.

Then we check the tap device box.

After that we type in the name of the tap device(I use soft here for simplicity).

Create Local Bridge

After the creation of the local bridge we jump back to our server. And run

1
# ifconfig tap_soft

It should show you something similar to this

Check on the server

Because we are not going to use SecureNAT and SecureDHCP. We need to install a DHCP server on our VPS. We are going to use dnsmasq as our DHCP server.

1
# apt-get install dnsmasq

Now edit the /etc/dnsmasq.conf file. Add these 3 lines at the end.

1
2
3
interface=tap_soft
dhcp-range=tap_soft,192.168.7.50,192.168.7.60,12h
dhcp-option=tap_soft,3,192.168.7.1

The above 3 lines are used to enable the dhcp server on interface tap_soft.

Next step we need a new set of init script which will config tap interface for us when Softether start up.

/etc/init.d/vpnserver
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#!/bin/sh
### BEGIN INIT INFO
# Provides:          vpnserver
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start daemon at boot time
# Description:       Enable Softether by daemon.
### END INIT INFO
DAEMON=/usr/local/vpnserver/vpnserver
LOCK=/var/lock/subsys/vpnserver
TAP_ADDR=192.168.7.1

test -x $DAEMON || exit 0
case "$1" in
start)
$DAEMON start
touch $LOCK
sleep 1
/sbin/ifconfig tap_soft $TAP_ADDR
;;
stop)
$DAEMON stop
rm $LOCK
;;
restart)
$DAEMON stop
sleep 3
$DAEMON start
sleep 1
/sbin/ifconfig tap_soft $TAP_ADDR
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
exit 0

Then we need to enable NAT on linux server.

Add this file to /etc/sysctl.d/ to enable ipv4 forwarding.

/etc/sysctl.d/ipv4_forwarding.conf
1
net.ipv4.ip_forward = 1

Apply the sysctl run

1
# sysctl --system

Then we add a POSTROUTING rule to iptables

1
# iptables -t nat -A POSTROUTING -s 192.168.7.0/24 -j SNAT --to-source [YOUR VPS IP ADDRESS]

To make our iptables rule survive after reboot install iptables-persistent

1
# apt-get install iptables-persistent

After all the above setting, restart the vpnserver then we are good to go.

1
2
# /etc/init.d/vpnserver restart
# /etc/init.d/dnsmasq restart

Comparison on SecureNAT and local bridge method.

Speed test on local bridge Speed test on SecureNAT

Conclusion

Local bridge use far less CPU resources than SecureNAT. It is a bit trouble to setup but I think it is worth to use local bridge.

I met with some amazing developers from Sqale.jp when I attent Ruby Conf TW 2012 last year.

Sqale is a japanese company compete with Heroku to provide developer friendly platform to host rails app.

Sqale is addressing some of the problems Heroku.

  1. Server location - Heroku servers are in US which is quite far away if the target audience are in APAC area.
  2. SSH access

    Since your app is spread across many dynos in the dyno manifold, there is no single place to SSH into. You deploy and manage apps, not servers.ref

  3. Slug size - Heroku limit it to a maximum 200MB.

Sqale provides server in Tokyo and gives developer a LXC container to work with. You can run cron job on Sqale without any changes if you migrate from dedicate server. So the platform dependent is lesser than Heroku.

For slug size, Sqale do not have a concept of slug. They give you 2GB of disk space for one container.

Pricing model

Sqale is charge by number of containers. Each one is ¥940 per month which is around 10USD.

How powerful is one container?

I am still testing out Sqale. Before I use Sqale in production I need to know what’s my operation cost.

Deploy a sample app

I always want to try out Swordfish. So I deployed it to sqale. The process is not too hard. But therer are lack of english documentation. I can only just guess what the console mean and try my best. Support from sqale is really helpful.

Static file test

I don’t want to test dynamic content yet. So I created a blank index.html in public/ directory and see how their nginx perform.

10 concurrent request warmup for 60 second

No error and response is steady.

1000 concurrent request for 300 second

Conclusion

First error start to occur when concurrent connection is about 815. The total error rate is 3% is not bad. You can scale out by adding more container to your application. But from what I understand from their website seems you can only add 4 more containers to your app. So maximum is 5 containers per app. I am not sure it is a technical reason or you can add more by contacting Sqale.

It also seems that they will help you do some ddos mitigation behind the scene. After the c1k rush I cannot run a smaller test on it. All requests are timeout.

I saw a post on lowendtalk last week introducing a new piece of vpn software call SoftEther.

What is SoftEther

A Free Cross-platform Multi-protocol VPN program, as an academic project from University of Tsukuba.

It is a single server which support SSL-VPN (HTTPS) and 6 major VPN protocols (OpenVPN, IPsec, L2TP, MS-SSTP, L2TPv3 and EtherIP).

I would like to also highlight the VPN over ICMP and VPN over DNS feature if you are inside a very strict network.

VPS Setup Guide

This post use SecureNAT. You may want to setup local bridge.

SoftEther author contacted me to highlight serveral points:

  • On physical server, local bridge will perform better than SecureNAT
  • DO NOT enable both local bridge and SecureNAT at the same time. Packets will loop infinitly and make your server 100% CPU usage.

Requirement: VPS

I am using vps from buyvm. I got from a year deal which is USD12/year. I would recommend Ramnode(affiliated) as a VPS provider. Their VPS is speedy and support is amazing.

  • Spec:
    • RAM: 128MB
    • Burst: 256MB
    • Disk Space: 15GB
    • Bandwidth: 500GB
    • Location: Buffalo, USA
  • OS:
    • Debian 6.0 64bit (minimal)

Make sure you login root as follow:

login as root

Before installing SoftEther Server let us install some prerequisite.

(build_tools.sh) download
1
2
apt-get update
apt-get install build-essential

Go to SoftEther to download the server binary.

download selection

I am using Ver 1.00, Build 9029, rc2 in this tutorial.

After download, run

(make.sh) download
1
2
3
tar zxf softether-vpnserver-v1.00-9029-rc2-2013.03.16-linux-x64-64bit.tar.gz
cd vpnserver
make

Read the Agreement and press 1 three times.

Then we move the dir to /usr/local/

(install.sh) download
1
2
3
4
5
6
7
cd ..
mv vpnserver /usr/local
cd /usr/local/vpnserver/
chmod 600 *
chmod 700 vpncmd
chmod 700 vpnserver
nano /etc/init.d/vpnserver

paste the following content to nano

(vpnserver.sh) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/bin/sh
### BEGIN INIT INFO
# Provides:          vpnserver
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start daemon at boot time
# Description:       Enable Softether by daemon.
### END INIT INFO
DAEMON=/usr/local/vpnserver/vpnserver
LOCK=/var/lock/subsys/vpnserver
test -x $DAEMON || exit 0
case "$1" in
start)
$DAEMON start
touch $LOCK
;;
stop)
$DAEMON stop
rm $LOCK
;;
restart)
$DAEMON stop
sleep 3
$DAEMON start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
exit 0

ctrl-o ret ctrl-x

After that we enable the service

(service.sh) download
1
2
3
4
5
chmod 755 /etc/init.d/vpnserver
mkdir /var/lock/subsys
update-rc.d vpnserver defaults
/etc/init.d/vpnserver start
cd /usr/local/vpnserver/

Then we need to do a checking.

1
2
3
./vpncmd
3
check

You should get 4 “Pass”.

We need to set the server admin password

1
2
3
4
5
./vpncmd
1
ret
ret
VPN Server>ServerPasswordSet

Enter the admin password.

I do the setting on a windows client. It is running

server manager

Install it, run it, click New setting. Input ip and password.

input setting

Then connect to it. On successful login, it will pop up Easy Setup

easy setup Check Remote Access Server and Next

warning

Yes

Virtual Hub name

OK

Setup L2TP Check Enable L2TP Server Function and input your own pre-share key

OK

Azure We disable Azure VPN

Create User

Then we need to create a new user. This is trivial.

User

Manager Click on “Manage Virtual Hub”

Click on “Secure NAT” (If you want a faster connection we can refer to my 2nd post on softether)

Secure NAT

Enable the Virtual NAT

Again DO NOT enable SecureNAT and local bridge at the same time!

Done

You can try to connect to the vpn server through L2TP/IPSec.

Background

There are often times in developing a CMS need to mark down who created the record. Django provide a nice admin interface for us. But when we only use the default, user need to select who they are by themselves. We want to auto select for them and they can’t pretend to be others.

code

In the django models.py, we have the following:

models.py
1
2
3
4
5
class Notes(models.Model):
    title = models.CharField(max_length=255)
    content = models.TextField()
    date = models.DateField()
    created_by = models.ForeignKey(User, related_name="Created By")

We want the created_by to be set automatically for the logged in user.

So in our admin:

admin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class NotesAdmin(admin.ModelAdmin):
    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == 'created_by':
            kwargs['queryset'] = User.objects.filter(username=request.user.username)
        return super(NotesAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)

    def get_readonly_fields(self, request, obj=None):
        if obj is not None:
            return self.readonly_fields + ('created_by',)
        return self.readonly_fields

    def add_view(self, request, form_url="", extra_context=None):
        data = request.GET.copy()
        data['created_by'] = request.user
        request.GET = data
        return super(NotesAdmin, self).add_view(request, form_url="", extra_context=extra_context)

admin.site.register(Notes, NotesAdmin)

explanation

The add_view function help us to select the current user from the drop-down list.

The formfield_for_foreignkey help us to filter out other users.

By combining this two function we get:

Created By

The last get_readonly_fields function make this field can’t be edit after the creation.