Monday, January 24, 2011

First practical joke with gncci - clamping the MSS

Today I thought that a great hack might be to try out per-host MSS clamping in userland.

Sounds like a fun idea, but ideas are not much without the execution - so this diff adds the hook for the setsockopt() - and, as a side effect the o.setsockopt() into the Lua-land. (The latter was actually what I wanted, but it was silly not to add the whole hook).

The result - it does wonders with PMTUD-blackholed websites, the world becomes wonderful again. All of this even without needing root to tweak the MTU on the physical interface.

Look, ma, no hands!

Sunday, January 23, 2011

gncci - general network connections contortion interface

Ok, the name is a bit wacky, because I wanted a bit of wordplay - the idea came up during the happy eyeballs discussion within the v6ops maillist, and I coded it up yesterday in one marathon run.

But I think the result is fun. You get an easy-to-tweak middle layer between the application making the socket calls and the socket calls proper. And it's not the C that you have to sweat in - it's all Lua baby.

So, by loading this with LD_PRELOAD you can code and a little bit of scripting you can do a lot of interesting things - check what connections the application is making, "sniff" the content that the app is sending onto the socket and receiving from the network, even deny some of the connection attempts or mangle the DNS packets so the application connects to the hosts that you have defined.

The possibilities are endless.

Bugs: it seems that the constructor code made it shaky. In retrospect, probably it should be protected with spinlock (similar to the existing code, which first was a spinlock, but then I discovered the multithreaded apps like firefox is might get into a deadlock - so I had to do thread-local variables).

Anyway, it works at least for some values of "works". Have fun.

Saturday, January 22, 2011

Export Mercurial repository into git repository

Wanna export mercurial or SVN repository to git ?

fast-export helps with that.

Thanks to Akhil for the tip.

The most interesting commands are: (to be done in the empty git repository that will be the target):

/path/to/ -r /path/to/hg_repo
git-repack -a -d -f

Friday, January 21, 2011

Sending the file descriptors between processes

What seems like very nice library:

This hides the intricacies of passing the file descriptors between the processes.

If it is portable enough, that'll be nice.

Wednesday, January 19, 2011

On ssl caching

tl;dr note for myself:

SSL-protected docs can be cached if you send the header "Cache-Control: public, max-age=31536000".

An elegant solution to avoid the hassle of explicitly specifying http/https references, assuming it does work (RFC says it should).

Tuesday, January 18, 2011

Politics as a catalyst of wealth

The world of politics, at least as far as I comprehend it - is very complicated. The politics, is, well, politics.

Must be especially tough close to the elections - I'd imagine this is the most impacting period. The tooth that was pulled out a year ago does not hurt - but the one that was pulled out yesterday hurts all right. It must be really tough to operate in such an environment. And then those lobbyist folks with their ideas...

So here's a thought experiment that I think might help the society get easier life for the politicians and for the society of the whole.

Abandon the elections.

Instead, mandate the direct democracy by law. Yes, by direct democracy, I mean the entities like Demoex in Sweden.
But, make such a technology country-wide and mandated.

"But laymen people are not great at taking the decisions" - you will say - "and, by the way, who has the time for this ?".

Precisely, this is where the catch is. Unless the things go utterly haywire, no-one *really* wants to deal with the mundane details. But, alas - you have to - it's by law.

But, the law also would not prohibit to hire someone to do this job for you. So we will have someone who will be paid to read the to-be-ratified papers and make the decisions on behalf of the others.

How's that called ? You're right - politician.

What's the difference compared to now ? The difference is the money flow. Right now it's faceless - the electorate pays the taxes, then they go to say "this guy will represent me for X years". And then the taxes pay the rent to that guy. As a result we have a fairly non-responsive system.

In the proposed equation - you can hire the guy per-month, per-week, per-hour if you wish.

The responsiveness to the customer needs would immediately be reflected in the rewards. The customers being those who do not have to spend the time on the elections - but simply outsource their responsibility to democratically decide. And the %% of the taxes that was going into the common flow of running expenses of the government, can be dramatically reduced.

Hey, but all of that would be a very bad idea! No-one would then take any unpopular decisions, because they are risky and unpopular!

The reality is:

  1. In business this works, with a suitable business plan.
  2. Else, noone is taking any unpopular decisions anyway - most of the time.

So it is not much worse than the status quo.

But, hey, what happens with all the lobbying that is supposedly [sic] happens ?

Simple. Convince the masses that Idea X is a good idea. Make a decent school in the neighborhood - and those who go there will become your live advertisement - much better than on TV. And they can then spend more time watching the actual film, anyway.

This all seems to be too simple to not have tried before and too simple to not contain any catch.

If you know some good historic examples on where this has been tried, I'd be curious to know the occasion and the outcome.

Compiling Lua on the fly with tcc.

tcc is quite fast.

This is in the "src" directory of Lua 5.1.4 (I added a small file with the definitions for the missing string functions).

$ time tcc *[^ca].c lgc.c lfunc.c -run lua.c -e 'print "hello!"'

real 0m0.165s
user 0m0.140s
sys 0m0.030s

Fun, even if fairly useless.

The performance of the lua interpreter that I had compiled statically, was about 1/2 of that compiled with gcc, so it is not a racer by all means - if you need speed, you will look at luajit.

Monday, January 17, 2011

Exploring the dimensions of lisp

On an orthogonal axis, a couple of interesting exhibits:

  • LuaLisp - lisp implemented entirely in Lua.
  • LispmFPGA - a lisp machine in FPGA project.

If I find something else worth adding - I'll update this post.

Windows 7 in kvm: some observations and tips

I spent the better part of this weekend reversing the status quo from running Ubuntu in VirtualBox on Windows 7 to running Windows 7 in kvm on top of Ubuntu. The result is catastrophic success, and makes me quite happy. This post is to share some little hacks/experiences that I've accumulated in the process.

  1. giving the "-usbdevice tablet" to kvm will avoid you from needing to click into the kvm window.

  2. using VNC to access the Windows VM is neat. This is achieved by adding "-vnc -daemonize" to the kvm command line. Handy when you have windows running long updates. You can simply close the VNC and let it chug along.

  3. typing "sendkey ctrl-alt-delete" into the monitor console (you get to it by pressing ctrl-alt-2 and back to gui by pressing ctrl-alt-1) [and, FWIW, using "F8" vnc popup, too] is a bit cumbersome. Therefore, since I'm going to use it alone, I'll redirect the console by "-monitor tcp:,server,nowait". Then I can create a shell script "send-ctrl-alt-del" that will contain the simple netcat call: "echo 'sendkey ctrl-alt-delete' | nc localhost 31337" - and then bind this to some key combo in fluxbox.

  4. do not be afraid to undershoot with disk space for win7. You can create a sparse 1gb file by doing "dd if=/dev/zero of=1gb.img bs=1024 count=1 seek=1048576" and then by appending this file to the image "cat 1gb.img >>win7.img". After that in the disk administration you can simply grow the volume by 1Gb.

  5. for accessing the files on host, if you do not have anything SMB-talking, you can get away with using the SSHFS. is precisely that. It allows userland filesystems as windows, and includes the SSHFS filesystem. It's a bit rough on edges, but works. Assuming you are using the kvm built-in networking, you will always connect to

    If this is your personal client machine, no need to keep ssh open to the world - so edit the /etc/ssh/sshd_config and put "ListenAddress" there. Do not forget to restart sshd afterwards.

    When you boot up your Windows you can connect the drives back to the host. Beware to turn off the cache - else the changes would not be reflected immediately and such a setup becomes tough to work with.

Hopefully this will be useful to you.

Sunday, January 16, 2011

How to disable touchpad on thinkpad laptops in X11

Thanks to Nico Schottelius for this hint.

In short, I needed to do three things:

  • xinput list - to find which ID does the touchpad have (11 for me)
  • xinput list-props 11 - to find which ID does the "enabled" setting have (125)
  • xinput set-prop 11 125 0 - to disable the annoying peripherial.

Saturday, January 15, 2011

How to quit smoking ?

I long wanted to share my experiences with getting rid of the tobacco addiction, and I've noticed one of my friends abandoning the habit of smoking, so this is a good trigger to do so.

So - how to quit smoking ? The first trick - don't. No, I do not mean continue smoking. Do not put this hard and fast barrier, this non-negotiable resolution - "never, never again". Phrase it differently for yourself - "I will stop smoking. Just for some time. I can always get back to it if I want."

Why do I say so ? Because smoking is an activity with an immediate short-term positive feedback, and big long-term negative feedback. But since human intuition is pretty bad at assessing the long-term events, the short-term positive has a much more dramatic impact. So, you put for yourself this prohibitive barrier. More over, it's not one but just two hardships that you create for yourself:

  1. The difficulty of having to survive the lack of the short-term positive feel of smoking
  2. The fear of guilt that you will experience when you violate your "never again" promise to yourself. This guilt will make your future 'quitting' attempts harder in itself - because you will be afraid of this negative feeling that comes when you would not be able to make it.

The second one has a huge ripple effect in my opinion - not only you are feeling the guilt in yourself violating your own promise, you also lower your own self-esteem. Subsequently you try to create an escape out of this labyrinth by either saying that it was not really 'for real' or that you have the unique condition which subjects you to strong physical addiction. Well, save yourself from this nonsense. Therefore:

Don't quit - but stop.

"quit" implies a one-time action (and 'never again') - while "stop" does not carry such a pathetic charge. It's simply a declaration of fact that you are transitioning from the smoking state to a non-smoking state. It leaves the freedom of the decision to restart smoking later, if you wish, up to you - without losing your dignity with yourself.

Isn't it good ?

Now, when we sorted out the self-guilt part, we need to figure out what to do with that urge. It's damn hard to avoid going for this awesome morning cigarette after you grabbed your first cup of coffee. Isn't it ? Do you feel this itchy feeling, that pushes you to run and get yourself a pack to get a puff ?

Well, that's my second lesson that I learned. Never try to stop smoking without significantly changing the environment/lifestyle - if you do, you are unnecessarily increasing the difficulty of your task. You don't do that with other activities - so why would you do it when it is about such an important thing as your future health ?

Also - when you change the environment and your schedule - ensure there is no "dead spot" that would make you think to fill it with smoking.

These two learnings make business trips and vacations an ideal place to stop smoking:
your environment is usually unfamiliar, so your mind is concentrated on reacting to the unknown factors rather than following the routine. As well - during these periods your schedule is usually busier than normal, which gives ever more distractions from smoking.

Another important thing that a change in the environment brings - it takes away the "social routine" aspect of smoking. By and large, the social part of smoking is probably the biggest drag of it - and by eliminating it, at least temporarily, you can make your life easier. (Later, when you restart the contacts with your smoker friends, you can simply mention to them that you were not smoking for a few weeks. This will gain you a whole lot of respect and awe from them :-)

The first key period is roughly about a week - that's when the real "physical" effects of nicotine wear out. (NB: This is totally unscientific, and is just my observation on myself). During this period you still may feel some "physical" urge to smoke.

You thought it'd get easier after that ? Well, the physical part is gone. But now we've got a much tougher nut to crack - it's in your head. It lasts about a month starting from your "stop point". At this point, while you are managing to abstain from smoking, the balance is very fragile - and a lot of factors can tip it.

The result of such a tipping will be an avalanche-like wave of desire to get a cigarette - which feels almost physical! Don't believe it - it is not. It's just your brain getting stuck. Whenever you get into such a situation, whatever happens, try not to think about the large green monkey with a banana. :-) Or, more seriously - just try to dissect what seems to be a physical need for a smoke into your reasoning on *why* it drags you there and what triggered it.

Some triggers that will probably cause you do it: a smoking scene in a movie. An argument with other people that will make you stressed and you will want to relieve the stress the same way as you'd do before - with a smoke. A time when you have to wait for something just long enough to have a cigarette. (programmers: "make all", anyone ?)

Fighting these urges is probably the toughest part in the whole exercise. I don't have a good recipe for it. Keep strong and remember that you can distract yourself by other activities. Like, watching this video about marshmallows:

So here we go, few weeks have successfully passed and you're so proud of yourself - you didn't smoke a single cig since you started. Time to pat yourself on the back! Also - note that now you are feeling yourself much better. You are less tired when you wake up in the morning. You have more energy throughout the day.

Note this good feeling well. Try to remember it very hard - and try to compare it with your feelings when you were regularly smoking. This is one of the ways you are building up your barrier to fall into puffing again - strengthening the current state of non-smoking.

But there it comes - somewhere along, friends get you to the party. Modest amounts of alcohol, and then there will always be a smoker at the party. You feel a desire that is irresistible. You think I'd say "be strong and resist the temptation?" Wrong. Go for it - full speed. Get a good doze of alcohol and feel free to smoke as much as you'd do before stopping. Why ? That's because in the morning you're gonna get a terrible hangover! The body, adapted to the absence of nicotine, will have to fight two poisons at once - alcohol and nicotine. A splitting headache guaranteed. So, if you are wise enough, reading this will be enough for you to not smoke that cigarette at the party. If you wanna try it out - go ahead. Just remember not to go overboard - I am not a doctor and I am not responsible if your body decides to go fubar on you.

Sometimes you may feel the circumstances warrant a cigarette - a good talk, what not.
Again - if you are sufficiently long into the process (say, 3+ weeks) - there is nothing to be afraid - you can use this to your advantage. Light up a cigarette, smoke it, and notice for yourself it feels like you put some shit in the mouth. So what was the point of putting it ?

If you repeat these exploratory actions not too close to each other (so as not to get the tastebuds numbed down by a smoke) - you can build a pretty good psychological link of cause-effect: "I puff a cig => it tastes like shit". It will be as good as once you might just ask yourself "so what's the point? I'll just stand nearby if all I wanna do is talk".

Eventually, you realise you have much stronger incentive psychologically to not smoke - and you build up enough of a set of short-term and near-short-term negatives to prevent your brain from tricking itself that it wants a smoke: headache, tiredness, bad taste while smoking, headache in the morning - these are all immediate enough to be quantifiably annoying (as opposed to some very distant death from some weird disease. Which will never happen anyway. 'Cos it's pretty hard for an individual to assess their own death. We overcome the fear of death back in the childhood and never re-learn to feel it again).

Why I say this can work ? I don't have a peer-reviewed scientific evidence to it. It's only based on my own experience. I managed to stop smoking once for half a year, when I was on a 1-month business trip, a few years back. Since then I was looking for a good occasion to repeat this - since I liked the feeling.

Last year starting March I completely stopped smoking - till September. In September I got a block of cigarettes as a present, which laid there for a few weeks, but then the physical presence of the cigarettes and a couple of "favorable" moments did make me pick up some of the smoking habit again. Which I promptly regretted - because I got used to that extra energy that I previously had. Mid-december I stopped again and hardly a couple of cigarettes since then - but I don't feel the "urge". Feels great not to have this dependency. And I do not have the guilt for temporary "restarting" fallback. I never promised to "never ever" in the first place - so I did not violate any promises to myself.

It's up to you to decide how much I practice what I preached here, whether to believe it or not, and whether it is better to stop smoking than to quit smoking. I'd be delighted to hear your results in the comments.

Wednesday, January 12, 2011

Initial 802.1q trunk support for ndpmon

I've spent a few hours tonight to add a feature I wanted to NDPMon - make it be able to listen on trunk interfaces.

1) only the monitoring part is supported for now, I did not even start
looking to the counter-measures.

2) "VLAN<n>:" is prepended to all the messages; "4095" signifying the
untagged frames, the other numbers mean the vlan# in the tagged frame.

3) obviously this is alpha - it can kill the newborn
kitten, cause lightning strikes and do other outrageous things.

If you're brave enough to mess around with it, head here: and give it a shot in your lab.

And then tell me something about your experiences.

Tuesday, January 11, 2011

IPv6-only networks in Ubuntu & co. and are the ones to watch if you have an IPv6-only network and Linux nodes. The older versions of the network manager assumed that the network that did not have IPv4 is "broken".

When I have a chance to test how this behaves in 10.10, I will update this entry.


10.10 has a much better knowledge of IPv6. So far I am pretty happy. To be tested is an IPv6-only network, but for that I need to install NAT64+DNS64, which I am not sure when I am able to do.

Random DNS requests from chrome / chromium

Was looking at the sniffer trace today and noticed that chromium on startup queries some seemingly random-looking names. Especially did not make a whole lot of sense that they are within the local domain.

Turns out that this is this is Chrome dealing with the ISPs who show ads for nonexistent domain names - if you do a single-word query, then Chrome looks it up in DNS, in the assumption that you were trying to reach your local server, and if the resolution succeeds, then it offers you "Did you mean ...?" popup at the top.

Obviously, if the ISP is hijacking the NXDomain, you will get "Did you mean ?" for *every* single-word query, which would be disappointing - so in case Chrome can make the requests to those "random names" (and I've verified that by installing a local wildcard DNS server + a web server on the box) - then it stops both the strange-looking DNS requests and the "did you mean ...?" popup.

EDIT: looks like I was too fast to judge that the "did you mean ...?" popup disappears - after some use, in fact it does not. OTOH, maybe there is some additional cleverness involved in Chrome's behavior - because I merely return the default lighttpd page to it.

Monday, January 10, 2011

The dusk

The dusk. The eyes do not adapt yet to the darkness that is blending its way in. Like in a bath that is cooling itself down, you don't realize when exactly does it get cold. When you do - it's already because of the tremolo of the teeth, it's too late. Or was it because you were slightly tired and fell asleep ?

Sleep is a treat - you get to appreciate it only when you lose it or can't have enough of it. Falling into momentary clouds of pleasure too strange to describe, only to jump out of it again less than a minute later. You know you should not, but it's irresistible to try again. Your eyelids drag you - stronger and stronger, until you give in again for a short blackout. And you're back.

The world is happily doing without you. Or so it seems. Did it get darker or you're just being self-centric ? It surely did get darker. But it's only one of the cycles. Don't take this personally. Better mind the damn steering wheel - you're on the road.

Sunday, January 9, 2011

Higher order functions as a building block for readable code

If you use a language like Ruby it's trivially easy to make DSLs and all this sweet-looking meta-programming stuff - you're lucky to be close enough to Lisp so you get the code that you can tweak the code before it's run. (attr_accessor, for example, is conceptually nothing more than a macro that expands into the reader and writer methods).

In Lua, you do not have that luxury. Well, you can have - if you install Metalua. But for my purposes this is usually a bit of using a nuke to shoot the pigeons. I want to minimize the number of dependencies - consequently, I try to rely on the stock 5.1 install as much as possible.

So, how does higher order functions help, you not getting a chance to do a "meta" code run ?

Because they allow the deferred execution.

This is a trick I used with this construct in gliese:

mongrel2connect {
sender_id = '558c92aa-1644-4e24-a524-39baad0f8e78',
sub_addr = 'tcp://',
pub_addr = 'tcp://',

-- Routing

get { "/", default_page, params = {
test = { optional },
get { "/foo", foo_page, params = {
test = { mandatory },
-- Anything else just redirect to root
get { ".*", redirect_request_to("/") },

mongrel2connect is a "real" function (the one that actually gets called and runs the loop servicing the requests)

whereas the "get" is the higher-order function. It returns a function that can be used to match the request against the supplied pattern to see if it is routable to the handler, and as well to check the parameters.

So, while the arguments for the mongrel2connect are calculated before the call to that happens, they can be used afterwards - thanks to the fact that the arguments do not do any action - but merely return the code to do the action.

This is a neat trick that allows me to make very readable code (at least for me:-) - essentially a DSL that you squeeze into a Lua table.

Friday, January 7, 2011

N-gram and regex search

So, I was thinking about the regex search in large volumes of data, and realized this should not be too hard to do. What do we do for a "usual" search: build an inverted index of stemmed words, and then match that with the query and intersect the word posting lists.

Now, imagine instead of words, we use the ngrams. Ok, here we have a little bit of a problem because if we are searching on "foobar" and we matched "foo" and "bar" we need to ensure they are also adjacent in the documents found. But, this should not be a big deal.

Now the interesting part. I am searching for a regex. Instead of matching the inverted index ngrams against the query string, I need to do something more clever. Let's pretend we have the regex implemented in terms as a DFA. A given ngram is suitable for the selection to begin with if it can result in valid transitions of the DFA. So for each of the states we can try to run the ngram against the DFA and see what gives. If this ngram does not give the good match, we discard it outright. If it does work - we store the acceptable chain of states.

Note that a single ngram might fire up more than once on a given regex - so we end up storing quite a few of possibilities.

Once we're done - we have a bunch of "broken chains" - because they are short. Now the task is to see if we can reconstruct the chain of the states from starting till ending one, and if we can - then this set of ngrams is a candidate set which can be used same as in the literal search onwards (e.g. in something like

The remaining question is what is the complexity of such a "glue" algorithm. The number of permutations to test can quickly become prohibitive.

What's in your name...

One of my friends expressed that she can not remember the names that sound pretty similar to her. I do have the same problem - and, as I learned a couple of times, at least my surname causes a similar stress in some folks.

But, I remembered, it's been quite some time I was joking that replacing the names with SHA-1 hashes would be way more practical.


1) SHA-1 hashes are all standard 40 bytes long hex numbers. This allows much more efficient storage of names in the databases and much more simplified input validation - it will be reduced to a trivial regex: /[0-9a-fA-F]{40}/ - and the input later on can be homogenized by lowercasing.

2) There's enough hashes to give everyone a unique ID. 2^140 which forty characters make, is huge. Of course, we need this huge number to prevent the hash collisions.
I should make the estimates of that a topic of a separate post.

3) The cryptographic hash is going to have pretty good distribution of digits. Corollary from this - means that within your circle of friends you do not need the full 40 characters. Much like close friends do not call you by surname - and just call you by name.

So, I've set out to look at (3) - because, obviously, the usability in this is paramount.

Short result: amongst the 370 friends I have on facebook, if they were to use SHA-1 hash of their name instead of their "real name", just five characters will be enough to uniquely identify all of them! This is even shorter than my own name!

So, it is very promising.

Here's how to do it in case you want to verify your own circle of friends (I take the facebook as an example).

Go to and click on the link next to the string "Friends: ". This will give you an ugly page full of JSON. Save it into file and go into the shell.

cat friends.json | sed -e 's/^.*\[//g' | sed -e 's/\].*$//g' | sed -e 's/[{}]*//g' | sed -e 's/,/\n/g' | sed -e '/^"id":.*$/d' | sed -e 's/"name"://g' >names.txt

Now that we have a list of names, let's make hashes. Simplest is to create a short script to hash its argument:

echo -n $1 | sha1sum

And finally we output the file running the hash on each name, then cutting out the first few characters, and seeing how many collisions do we get:

$ cat names.txt | xargs -n 1 sh hash | cut -c 1-3 | sort | uniq -c | grep -v ' 1 '
2 2c3
2 3d5
2 4fe
2 6ef
2 b32
2 b52
2 b7e
2 c78
2 c9f
2 d6f
2 e42
2 e6f
2 f69
2 ff5

So, with just three(!!!) characters of the hash there only a handful collisions.
Using couple more characters eliminates them and as well gives an ample room for a collision-free growth of my friend list.

And maybe now you get an idea why at the top of the page there's this row of hex, to begin with.

I think using the hashes instead of name is indeed much more practical than trying to remember the names - c3e9f, do you agree ? ;-)

Tuesday, January 4, 2011

Ivory tower gurus...

I've seen this Dilbert in this IOSHints blog entry, here's what I think:

(I wish I could write about memory, layers of indirections, and such - but there was only so much space).

Why do people think that politicians need to learn history, but the technologists do not ?

Sunday, January 2, 2011

correct scapy2 import statement


>>> from scapy import all
>>> a = IP()
Traceback (most recent call last):
File "", line 1, in
NameError: name 'IP' is not defined


try:from scapy.all import * #Required for Scapy 2.0 and above
except:from scapy import * #Scapy 1.0

(via Tim Eberhard's post. On a side note, here's a pretty uselessly closed bugreport.)

Saturday, January 1, 2011

Mongrel2 and SSL

Mongrel2 supports SSL. Well, actually TLS, to be exact. To be running it you need a version with the small fix that disables the default built-in key during axTLS' SSL context initialization.

There are two steps you need to do to get your server support TLS-encrypted connections:

1) edit the config file

main = Server(
. . . [snip]

servers = [main]

settings = {
"f400bf85-4538-4f7a-8908-67e313d515c2.use_ssl": 1,
"certdir": "./certs/"

Needless to say that the plaintext will no longer work on this server entry.

2) generate the private key and obtain a certificate

This is something that is widely covered on the Net. If you want to install a self-signed cert for testing, there is a good doc that describes how to do it.

The key mongrel2-specific part here is that the private key file is named <Server-UUID>.key, and the certificate is in the file <Server-UUID>.crt

(note: a "private" key is called private for a reason. You do not want anyone except the mongrel2 to be able to read it. So, mind your permissions).

For the lazy

I've added a sample static SSL site as well to Mongrel2 Hacking In a Box repository.
It has a canned config, also a pre-generated dummy key and cert, as well as a script to regenerate them.

Happy hacking!


If you are trying with chrom(e|ium), chances are that it would not work correctly - at least it did not work for me. Seems like it is a bug in the built-in SSL library which does not want to do TLS1.0, only SSL3.0. To cure this, you need to launch the chrom(e|ium) so that it uses the system SSL library:

$ chromium-browser --use-system-ssl

Notably, it was not always that I experienced this failure - the problem did is not reproducible enough to debug it for now. If you find anything - let me know.