Mailman Subscription Spam

In the last few weeks, a few of us running mailman have been noticing attacks using our servers. Most often we end up being used as…

In the last few weeks, a few of us running mailman have been noticing attacks using our servers. Most often we end up being used as relays to send subscription spam to the servers. They pick one address and use multiple aliases of the address to send spam to. I won’t get into the details of the attack, but here’s a script that I came up with and is now modified to be friendly thanks to OpenStack Infra Team.

Create the file /usr/lib/mailman/bin/ban.py with this content:

def ban(m, address):     try:         m.Lock()         if address not in m.ban_list:             m.ban_list.append(address)         m.Save()     finally:         m.Unlock() 

Now run this script like this

sudo /usr/lib/mailman/bin/withlist -a -r ban "<address to ban>" 

The ban address can be a regular expressions, so to ban an address and all suffixes, use ^address.*@example.com as the address to ban.

Update: Matthew Saltzman pointed out that the . in .com needs to be escaped as well.

Weird IE8 error. Nginx to the rescue!

As a server side developer, I don’t run into IE-specific errors very often. Last month, I ran into a very specific error, which is spectacular by itself. IE8 does not like downloads with cache control headers. The client has plenty of IE8 users and preferred we serve over HTTP for IE8 so that the site worked for sure.

Nginx has a very handy module called ngx_http_browser_module to help! All that I needed to do was less than 10 lines of Nginx config.

location / {     # every browser is to be considered modern     modern_browser unlisted;     # these particular browsers are ancient     ancient_browser "MSIE 6.0" "MSIE 7.0" "MSIE 8.0";     # redirect to HTTP if ancient     if ($ancient_browser) {         return 301 http://$server_name$request_uri;     }     # handle requests that are not redirected     proxy_pass http://127.0.0.1:8080;     proxy_set_header X-Forwarded-For $remote_addr;     proxy_set_header Host $host;     proxy_set_header X-Forwarded-Proto $scheme; } 
It's Magic GIF

Yet another day I’m surprised by Nginx 🙂

Deploying automatically with webhooks

Recently, we had a project deliverable to setup a repository that would auto-deploy to the staging server. I spent a bit of time getting this right, so I figured it’d be useful for someone else who had to do this.

Recently, we had a project deliverable to setup a repository that would auto-deploy to the staging server. I spent a bit of time getting this right, so I figured it’d be useful for someone else who had to do this.

Code

I wrote cloaked-spice, a tiny Flask app to do the job here. Flask documentation has a pretty neat example for doing request checksums. I’ve just modified it to work with HMAC and SHA1. It sounds simple, but thanks to silly mistakes, it took a few days to get it working 🙂

Server Setup

The Flask app is extremely limited in what it can do on the server. It is run as a user called deploy and a group called deploy. All the files that the app can update are owned by the group deploy and editable by the group. Thanks to sudo’s flexibility, it can only run one sudo command. Here’s the line in sudoers file:

deploy ALL=(ALL) NOPASSWD: /usr/bin/service apache2 * 

Serving cloaked-spice

I’m using gunicorn and Nginx to serve the app and supervisor to manage the gunicorn process. I’m sure other wsgi servers would be up-to the job just as easily.

Credits to Github for suggesting a name for this that sounds less boring that deploy.

Arrrgh! Tracebacks and Exceptions

My colleague asked me to take a look at a logging issue on a server last week. He noticed that the error logs had way too little information about exceptions. In this particular instance, we had switched to Nginx + gunicorn instead of our…

My colleague asked me to take a look at a logging issue on a server last week. He noticed that the error logs had way too little information about exceptions. In this particular instance, we had switched to Nginx + gunicorn instead of our usual Nginx + Apache + mod_wsgi (yeah, we’re weird). I took a quick look this morning and everything looked exactly like they should. I’ve read up more gunicorn docs today than I’ve ever done, I think.

Eventually, I asked my colleague Tryggvi for help. I needed a third person to tell me if I was making an obvious mistake. He asked me if I tried running gunicorn without supervisor, which I hadn’t. I tried that locally first, and it worked! I was all set to blame supervisor for my woes and tried it on production. Nope. No luck. As any good sysadmin would do, I checked if the versions matched and they did. CKAN itself has it’s dependencies frozen, this lead to more confusion in my brain. It didn’t make sense.

I started looking at the Exception in more detail, there was a note about email not working and the actual traceback. Well, since I didn’t actually have a mail server on my local machine, I commented those configs out, and now I just had the right Traceback. A few minutes later, it dawned on me. It’s a Pylons “feature”. The full traceback is printed to stdout if and only if there’s no email handling. Our default configs have an email configured and our servers have postfix installed on them and all the errors go to an email alias that’s way too noisy to be useful (Sentry. Soon). I went and commented out the relevant bits of configuration and voilà, it works!

Palm Face

Image source: Unknown, but provided by Tryggvi 🙂

OKFestival Fringe Events

The writeup of the OKFestival is very incomplete, because I haven’t mentioned the fringe events! I attended two fringe events and they both were very good.

The writeup of the OKFestival is very incomplete, because I haven’t mentioned the fringe events! I attended two fringe events and they both were very good.

First, I attended CKANCon right before OKFestival. It was informal and co-located with CSVConf. My best takeaway has been talking to people from the wider community around CKAN. I often feel blind-sided because we don’t have a good view of CKAN. I want to know how a user of a portal built on CKAN feels about the UX. After all, the actual users of open data portals are citizens who get data that they can do awesome things with. I had a good conversation with folks from DKAN about their work and I’ve been thinking about how we can make that better.

I finally met Max! (And I was disappointed he didn’t have a meatspace sticker 😛

The other event I attended was Write the Docs. Ali and Florian came to Berlin to attend the event. It was total surprise running into them at the Mozilla Berlin office. The discussions at the event were spectacular. The talks by by Paul Adams and Jessica Rose were great and a huge learning experience. I missed parts of oncletom’s talk, but the bit I did catch sounded very different to my normal view of documentation.

We had a few discussions around localization and QA of docs which were pretty eye opening. At one of the sessions, Paul, Ali, Florian and I discussed rules of documentation, which turned out pretty good! It was an exercise in patience narrowing them down!

I was nearly exhausted and unable to think clearly by the time Write the Docs started, but managed to face through it! Huge thanks to (among others ) Mikey and Kristof for organizing the event!