Securing my Clojure photo gallery: Let’s Encrypt certs on NFSN

January 10th, 2017

I have a photo gallery site written in Clojure, hosted at NearlyFreeSpeech.NET. I just spent less than an hour learning about ACME and successfully hooked up my app with TLS! Here's what I did.

In my case, the Clojure application is packaged up as a .jar file, and is run as a daemon behind NFSN's reverse proxy, which is capable of terminating TLS. They also provide a script, lets-nfsn.sh, that can do the ACME challenge-response. However, it does this by dropping the response files in the Apache-served public directory, which isn't exposed in my configuration.

I chose to modify my application to proxy the acme-challenge dir. It has risks; if you screw up filesystem proxying, you risk path traversal attacks that allow an attacker to read anything on your filesystem! Anyway, it takes very little code, and it worked on the first try, so I would encourage people to use this method.

Below is the meat of the commit that implements this. It's not very much!

(ns org.timmc.pellucida.res.acme
  "Pass through ACME requests to filesystem. (ACME: Automated
Certificate Management Environment)"
  (:require
   [compojure.core :refer [defroutes GET]]
   [org.timmc.pellucida.settings :as cnf]))

(defn is-token-shaped?
  "Does this string look like an ACME http-01 token? In particular,
does it *not* look like a path traversal attack?"
  [^String s]
  (boolean (re-matches #"[a-zA-Z0-9\-_=]+" s)))

(defn token-response
  "Answer with the contents of the ACME challenge file."
  [magic-token]
  ;; The ACME http-01 token value is used as the filename as well
  ;; as the value of a field within the JSON file.
  (when (is-token-shaped? magic-token)
    (let [resp-path (str (:acme-challenge-dir @cnf/config) "/" magic-token)]
      {:status 200
       :headers {"Content-Type" "text/plain"} ;; Spec: This or none
       :body (java.io.File. resp-path)})))

(defroutes acme-routes
  (GET ["/.well-known/acme-challenge/:magic-token"] [magic-token :as r]
       (when (:acme-challenge-dir @cnf/config)
         (token-response magic-token))))

Incidentally, there were a few other options I thought of, but did not pursue or fully evaluate:

  • Hook: lets-nfsn.sh uses dehydrated to implement ACME, and you can hook into it for various events, including challenge generation. I could use that to notify the app to do something.
  • Proxy: I already configure the NFSN site to proxy the root path to my app's port 8080. Could I add another proxy that just mirrors /home/public/.well-known/acme-challenge? Not sure. From the forums, it sounds like if I change the site type to "Apache2.4 generic" instead of "Custom", I could possibly do this. Ah well, the code is already written!

Can we have online journaling while maintaining privacy?

November 27th, 2016

I've been blogging for over 11 years now, for better or worse. I cringe a bit when I look back at some of my older posts, but I'm loathe to delete them, because it's who I was then. I've also maintained a Livejournal (LJ) or Dreamwidth (DW) account for almost as long, where I've made posts of a more personal nature. How did I decide where to post, where the dividing line was? It came down to two things: 1) How personal the post was, and 2) where my intended audience was. Back in the mid-00's, many of my friends and acquaintances had public blogs, but were no on LJ. That meant that if I wanted them to know how I was doing, I had to post for the world to see, even if that meant future employers with boundary issues would see those posts out of context. As the blogosphere slowly deflated and I entered Boston-area social groups where LJ was more common, the choice became easier. Then Facebook rose to supremacy, and I chose not to jump off that particular bridge... but now it's much harder to have an online social life.

I really miss that, but Facebook is not an option. How can we return to the days of easy journaling? I'd like to lay out what I see as (a) central problem, then ask you for ideas in solving it.

Read full entry »

Buying laptops sucks, online stores make it worse

November 25th, 2016

We recently had to go shopping for a new laptop, and since Lenovo's design is going down the shitter, we had to do more research than usual.

Read full entry »

The invisible tchotchke

September 14th, 2016

There's a yard I see periodically that is both well-landscaped and also absolutely filled with stuff: Tchotchkes, baubles, and knick-knacks but also random other items of interesting appearance such as bird cages, dolls, or colorful tiles. While it could look terrible, the owner has arranged them and worked them all in with the plants and the overall effect is quite pleasing, although I'm sure there's at least one angry neighbor.

What I found surprising on my first encounter was that the objects seemed to have some sort of mystical power to avoid individual visual inspection. When describing this yard to someone a few days ago, I found myself unable to recall any one of the objects in particular, and had to fall back on the generic "tchotchkes". The next time I went past, instead of allowing my eyes to drift over the whole collection, I tried to focus on any one object, and found that I could not! It was rather disconcerting.

I had originally chalked this up to the distracting nature of the entire yard, but I think there's more to it than that. The third time, I introspected while attempting to examine a single object, and found that when my eyes wandered, it was in service of discovering the context of the object. This makes sense! We understand our visual world contextually, and I believe Hofstadter & co. are correct in their top-down + bottom-up Fluid Concepts model—there is an interplay between forming expectations based on observations and fitting observations to expectations. We understand an object (faster) by what is around it: A fork on the kitchen counter amid some dirty dishes is easier to recognize at a glance than, say, a fork in the road. But the objects in this yard are not only completely removed from their original context, they are placed into a distracting one, and even worse, a field of other contextless objects! And so my eyes wander out to the next object over, and the next, and then distraction takes hold.

As I was writing this, I think I have found one other situation where this effect takes place: A very messy room or desk, full of odds and ends. I find that when I set myself to the task of cleaning a mess like that, I freeze up. I had thought that perhaps it was due to the energy required to make a hundred small decisions (that had already been deferred for their non-triviality—there's a selection effect at play here) but now I wonder if perhaps I am also having difficulty focusing on any object long enough to tackle it. Certainly this would interfere with my ability to "pick the low-hanging fruit". If true, I might be able to develop some strategies for cleaning my desk, such as picking an object randomly and considering it outside of the desk's context.

I'm curious to hear if others have experienced this phenomenon as well. I'm also curious whether it correlates to any degree with attentional issues (e.g. I have ADHD) or visual processing issues. Or perhaps this is just an idiosyncratic trait, but if there's anything I've learned about the internet, it's that there's usually a "me too!" out there somewhere.

strace’ing a Clojure process under lein

August 16th, 2016

Today I wanted to strace a JVM process to see if it was making network calls, and I discovered a minor roadblock: It was a Clojure program being run using the Leiningen build tool. lein run spawns a JVM subprocess and then exits, and I only wanted to trace that subprocess.

Read full entry »