Yearly Archives: 2016

MapTable.js for all your table and map needs!

2 minutes, 13 seconds

I’m proud to announce that I played a small role in releasing a great new JavaScript library called MapTable. This is an open source JavaScript library that accepts longitude and latitude data (CSV or JSON) as input, and outputs beautiful maps in native SVG with table of the data used to generate the map.  I said I played a small role in this release because Mohammed “Simo” Elalj did 99% of the coding of the library and I just swooped in for testing, PCH specific feature requests and pushing out new builds to GitHub. Version 1.0 of MapTable was technically released way back in December of 2014, but it has been greatly improved since then (again, almost entirely by Simo :).

pch.ixpdir.maptableVersion 1.1.1, the current version, was developed specifically so it could be used on PCH’s next generation Internet Exchange Point directory (IXP Dir). PCH’s IXP Dir was also the original use that MapTable was conceived for, so it has been a long journey until just now (as of Monday, July 25, 2016) that it has been pushed live!  My main role as an employee of PCH was to complete the nascent integration done a while ago and ensure that all feature requests were made on GitHub so that the improvements would be made upstream of us for all to benefit from. It was great fun to do a deep dive into a well though out and highly function JS library.

pch.homepageWhile I was in the IXP Dir, I also replaced the code on our home page which used an outdated version of MapTable. Fortunately, Simo had done PCH the huge favor of making one of the MapTable demo pages be based almost entirely on our home page. The ability to set an entirely custom color palette topped with icing on the cake of being able to specify an arbitrary SVG shape to use as markers on the map was just delightful!

While I’m wildly biased, MapTable is quite easy to use. Here’s the simplest incantation, taken directly from our docs:

Looking at the two examples I cited above, our home page and our IXP Dir, you can see that this simple snippet can be greatly extended to show either a stand alone map or an interactive, zoomable, filterable, printable, map downloadable, tooltipable and sortable map and table. The library is super awesome, and I recommend you start using it today! And yes, I just add “able” to tooltip. Try that in some other JS lib. I think not!

And, before I end this post, if you’re a JS developer and have some spare time, we’d love some help! I’m looking at you Issue #25!

Scanning multiple subnets for SSH servers that accept passwords

1 minute, 25 seconds

At work I was tasked to see if any of our servers are running SSH which allow passwords instead of strictly only allowing SSH keys.  You can tell if they allow passwords when you get a password prompt like this:

$ ssh's password:

Of course we’ll use nmap to scan for open SSH ports. I suspect I should have have used nmap NSE to do scripting, but we’ll plod ahead with out it.  Here’s the call I used to scan each subnet for open SSH ports and append it to ‘open.raw.txt’. Run this for each of your subnets:

nmap -PN -p 22 --open -oG - >> open.raw.txt

Here’s an example line from open.raw.txt:

Host: ()	Status: Up
Host: ()	Ports: 22/open/tcp//ssh///

To get that all formatted nice for the next phase, we’ll just cut out dupe and grab just the IPs:

grep 'Up' open.raw.txt |cut -d' ' -f2 > open.ips.txt

Finally, taking much inspiration from this script on StackOverflow, I wrote a bash script to check for servers with a password prompt on SSH called

proc isHostAlive {host} {
set timeout 5 
spawn ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=QUIET -o PasswordAuthentication=yes ssh-testing@$host
expect {
    timeout {puts "Timeout happened"; return 'TIMEOUT'}
    eof {return 'NO'}
    -nocase "password:" {send "exit\r";return 'YES'  } 

# Lists to maintain the each host's information 
set serverList {}

# Looping through all the servers and checking it's availability
foreach server $serverList { 
    puts "\n$server : [isHostAlive $server]\n"

To execute and log the results, call: > password.accepted.raw.txt

And finally, to clean up those results into a file with “YES”, “NO” or “TIMEOUT” for each IP, just use this final grep

egrep  'YES|NO|TIMEOUT' password.accepted.raw.txt > password.accepted.txt

The final results will look like this: : 'YES' : 'NO' : 'YES' : 'YES' : 'TIMEOUT'

Happy SSH testing!

Ubuntu 16.04 on Dell XPS 13 9350 (Updated 11/24/16)

4 minutes, 52 seconds

Why upgrade?

dell.xps.12.deAfter watching my shopmate get one, then seeing The Wirecutter recommend it (as of May 2016) and then seeing Dell upgrade it, I was very tempted to get a Dell XPS 13 and run Linux on it.

The straw that broke the camel’s back was seeing factory refurbished ones with 16GB of RAM, 512GB of disk, an i7, a Dell 1 year warranty and that gorgeous QHD+ resolution (3200×1800) for less than $1,300 on eBay (again as of May 2016). This is is about $700 off of retail for a comparably equipped machine (or a lot more). Though this ships with Windows 10, I figured I could install Ubuntu on it.

Ubuntu 16.04 install

Xerus_White-1024x576Before pulling the trigger on eBay, I did a lot of reading on the forums about how to install over windows. Specifically, posts like this we’re key. I knew in the BIOS that I needed to turn off Secure boot and switch disk mode to AHCI. Further reading suggested that it might be a real uphill battle to get everything, hardware wise, working.

I’m happy to report that just about everything works under 16.04! I installed it after making an install image after USB boot drive from the .iso. The touch screen doesn’t work after suspend. I was hopeful that the xinput enable/disable trick might fix it, but no such luck just yet. Given that you can’t do single finger scroll and pinch to zoom when touch is working, I’m not too bummed about this.

I was very pleased to see that this cheap USB-C to DisplayPort adapter works great. Though it can’t quite do 4k (resolution shows in “Displays”, but my Dell won’t show an image), it will do all resolutions below that. It works on boot and after repeated hot swaps. The cheap USB to Ethernet adapter worked flawlessly as well, Handy times!

The other pleasant surprise was that the Broadcom WiFi/Bluetooth card also seems to just work under 16.04. Admittedly, I’ve just been using the WiFi with no problems and haven’t tested the Bluetooth.

The trackpad works as well as my MacBook Air trackpad did under 14.04. It looks like there’s some PS/2 vs Native twiddling that might improve palm detection, but I’m happy with it as is given it’s status quo for me.

Software and eBay

air.ebayThere’s a little hiccup with OwnCloud resetting after suspend or WiFi hopping, but this is nothing to do with the XPS 13, and everything to do with 16.04. As well, the version of KeepassX that ships with 16.04 no longer supports the old version 1 flavor of the password safe. It was high time I upgraded to version 2 anyway!

Finally, anyone want to buy an 11″ Air formerly running Ubuntu 14.04, but now with a clean install of El Capitan?

6/2/2016 Update

intel.cardAfter having this laptop for a bit now and having made a few tweaks, I wanted to update this post. The first, and most important, change is that I found the Broadcom chip I mentioned above did not “just work”. Though strictly anecdotal, I found that the card had intermittent high packet loss on WiFi and was actually unusable when I went to use my Bluetooth mouse for a few hours. Swapping out the card it shipped with for the Intel 7265 802.11ac one, instantly solved all these problems. The Intal card may have caused WiFi to stop working just once after a bunch of suspend and resumes, but I can’t remember so it must not be that annoying ;)

Two notes on replacing the card: The first is that while the Amazon link cited for this is certainly the right price at $20.99 (as of Jun 6 ’16), it is a bit slow in shipping. The second is that you should totally use iFixit’s XPS 13 tear down guide as a how to for opening this laptop. As well, they cite the online Dell repair manual (pdf), if you want to reference that. And, yes, when iFixit says the bottom of the laptop takes more force to open than you think it should, they’re totally correct!

The other big change is that I installed TLP in hopes of improving battery life. Using the default config out of the box seems to yield good results. However, this is just anecdotal evidence again, nothing scientific.

Otherwise, the general update is that this laptop continues to rock. I use it about 3-10 hours a week, including some intense 4 hour work sessions at the cafe. For full dev environment I run two vagrant VMs on Virtual Box along with Chromium, Firefox and PHP Storm as my IDE. I’m pretty sure I could get 6-8 hours of battery life running these apps if I was conservative with the screen brightness. Some times when I resume it, I’ll see 14 hours remaining in the battery life. It almost always drops down, but still neat to see.

It looks like you can still get this bad boy on eBay for just under $1,400!

8/13/2016 Update

I’m still totally loving this laptop! Seeing my wife get more comfy with her laptop and it’s touch screen, I wondered if I could find a fix for mine under 16.04. After some searching around a found a fix that is…so simple it’s silly. Quickly close and open the lid:

close the lid just to enter suspend state, but then reopen it quickly, so that it stays in suspend state even when the lid is open. Then press power button to wake it up. Then the touchscreen works again!
xps9350: touchscreen stops working after sleep

After testing this over the last 4 days, I can confirm it works. Coupled with the fact that the OS and Chrome/Chromium handle single finger scroll and pinch to zoom, I’m a happy camper! The icing the cake was finding the Grab and Drag plugin for FireFox. Though pinch to zoom doesn’t work, single finger scroll does. Handy times!

11/24/2016 Update

One my fine readers pointed out that the touch screen under 16.04 has been more properly fixed. This is awesome! This gist on github has all the info you need. Be sure you read the part about using uname -r to get your kernel and make sure it matches on the line that the script is hard coded against. For it it was 4.4.0-45, but for the original author it was 4.4.0-47. As well, it didn’t fully start working for me until a restart.

5/17/2018 Update

Almost exactly two years in and this laptop is still my daily driver! It’s been *super* stable and I’ve had no problems with it. I’m still on 16.04, despite 18.04 having just been released. Also, check out my latest post about USB-C accessories I’m using!

Web App Security Cheat Sheet

1 minute, 36 seconds

I recently documented best security practices for writing a web app. Since I was most of the way there for a nice tidy blog post on the topic, I’m using the contents of those docs as a cheat sheet for web app security. Best to refer to OWASP for a more exhaustive list, but here’s mine in PHP/Apache:

title description sample
No Traffic on Port 80 Always use an encrypted channel for web traffic, never send a session cookie in the clear RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
HSTS Set header so after 1st redirect, client goes directly to SSL connection Header always set Strict-Transport-Security
Forward Secrecy Use ephemeral keys for TLS connections to prevent wholesale decryption if private key is compromised SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
SSLProtocol All -SSLv2 -SSLv3
SSLHonorCipherOrder On
Anti-Clickjacking Prevent your site from being included in an iframe Header always set X-Frame-Options DENY
Anti-CSRF Nonces No one getting tricked to submit pre-filled forms using their existing session cookie $_POST[$NONCEKEY] == $_COOKIE[$NONCEKEY]
(but more to it – see this gist)
XSS escaping NEVER TRUST USER INPUT, save raw values to DB, cleanse on display print htmlspecialchars($user_string_here, ENT_QUOTES, ‘UTF-8’)
Secure cookies Never transmit cookies in the clear, works well with HSTS setcookie( ‘session’, $sessionId, 0, ‘/’, ‘’, isset($_SERVER[“HTTPS”]), true);
HttpOnly cookies don’t allow JavaScript/XSS to access your cookies setcookie( ‘session’, $sessionId, 0, ‘/’, ‘’, isset($_SERVER[“HTTPS”]), true);
bcrypt hashes Use a *slow* hashing method instead of a *fast* one (I’m looking at you MD5…) password_hash(“rasmuslerdorf”, PASSWORD_DEFAULT)
Though Argon2 is up and coming!
strong session ID don’t store anything but pseudo random ID in the cookie. Again NEVER TRUST USER INPUT! bin2hex(openssl_random_pseudo_bytes(50))
no session fixation on logout, delete cookie **and** server side entry in DB so session is dead dead dead NA
re-prompt for passwords on email, password or username change or when showing/changing sensitive data NA
no SQL injection still NEVER TRUST USER INPUT, parameterize all queries $dbh = new PDO(…);
$stmt = $dbh->prepare(‘SELECT * FROM users where username = :username’);
$stmt->execute( array(‘:username’ => $_REQUEST[‘username’]) );

Penance for forgetting basic debugging

1 minute, 56 seconds

I was working on implemented a nonce to fight CSRF requests on all our forms. The nonce worked liked you expect: by setting a cookie and then putting the same value in the form. When the form was submitted, the back end checked that the form nonce matched the cookie nonce and, bam, bob is your uncle.

The HTML for the form was hosted on and was fetched via an AJAX call to render it in a modal on It used a JavaScript function that looked like this:

      id: "login",
      primary_button_action: function(){
        $('form #loginform').submit();
      url: URL_ROOT + "modal/login",

Now, you can’t quite tell, but this is ultimately a wrapper for Twitter’s Bootstrap’s Modal call:


For the life of me I could not figure out when the AJAX call from foo subdomain to bar subdomain was not setting the nonce cookie. I thought it would be a CORS issue, but quickly dismissed that because we all know that “AJAX Requests Get And Set Cookies Like Any Other HTTP Request“, right. RIGHT?!!?

I did follow the best practice of putting in poor man’s PHP break points to trace the $_POST and $_COOKIE values, but to no avail.

After far too long, but after a healthy discussion with a friend about how we learn and how we trouble shoot, I remembered my mantra I always tell junior engineers: “Simplify the problem! Distill it down. Ideally, continue to cut the code in half again and again until just the bare minimum manifesting the problem remains.”

This lead me to reproduce the problem in two lines of code on to call

The problem was still there! No nonce cookies getting set. Let’s remove jQuery then and go to raw JS requests:

var xhr = new XMLHttpRequest();'GET', '', true);
xhr.withCredentials = true;

Wait ah second! What was that I see in the console?!@@!#%$:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at (Reason: CORS header 'Access-Control-Allow-Origin' does not match '*').

Oh…CORS…the thing I dismissed upfront. So, yes, AJAX calls are just HTTP requests per’s blog post, but of course if foo subdomain is calling the modal on bar subdomain via AJAX, it’s an XHR request to another (sub)domain which needs to play by CORS rules.

If any one is interested, I published a gist with our PHP code to do nonces.

Diceware in a box

1 minute, 2 seconds

I’m really happy with my most recent project I did at the shop. For some time now I’ve been wanting to upgrade from a mostly secure password to a phenomenally secure passphrase. For some down home good entropy, you should use the Diceware method to generate a passphrase. In order to achieve this, I made a “Diceware in a box”.  The ingredients for this recipe are:

Here’s what the final product looks like (click to see larger version):


The only changes from my original design I would do is instead of scrounging up some rubber feet to put on the side so the dice bounce instead of slide, is that I’d just lay down long strips of hot glue on the inside. This would achieve the same affect and be a lot easier.

Here’s the product in action:
And here’s the result (please do not post your passphrase to the internet ;)

range herr vq fr kirby dad pp!!!

Top Posts Update

0 minutes, 54 seconds

A while ago I did a write up of the top blog posts on this site.  Oh…um, I guess that was 5 years ago now.  Wowaa.  Well, Here’s the same script run again to give you an idea of what’s popular:

$ grep 'GET /blog' plip_log/access_log|cut -d" " -f 7|egrep -v '.png|.jpg|wp-includes|.css|/page/|/category/|xmlrpc|wp-trackback|/feed/|wp-login|/wp-content/|/trackback/|wp-comments|wp-app.php|wp-admin|comment-page|index.php|?p=|page_id|comments|feed'|sort|cut -d"/" -f 3|uniq -c|grep -v ' 1 '|sort -nr|head
   1026 free-idea-abstracted-facebook-nonymizer
    959 adendum-to-ashleys-law-problematic-imac-vesa-mounts-and-new-desks
    805 toss-your-salad-code
    693 thoughts-on-very-large-monitors
    650 photos-food-bikes-sunsets-and-stars
    635 sunset-and-rainbows
    385 oakland-sf-photos-coffee-and-scotch-whiskey
    373 wayback-machine-privacy-and-old-plip-com
    361 how-i-make-coffee
    330 our-pet-venus-fly-trap

This may make them all the more popular, but here’s the links for them:

1026 free-idea-abstracted-facebook-nonymizer
    959 adendum-to-ashleys-law-problematic-imac-vesa-mounts-and-new-desks
    805 toss-your-salad-code
    693 thoughts-on-very-large-monitors
    650 photos-food-bikes-sunsets-and-stars
    635 sunset-and-rainbows
    385 oakland-sf-photos-coffee-and-scotch-whiskey
    373 wayback-machine-privacy-and-old-plip-com
    361 how-i-make-coffee
    330 our-pet-venus-fly-trap

A few updates on these post’s topics:

  • A lot of the images are broken on older posts. I think this has to do with going all HTTPS and as well some munging of the markup to rendered HTML.  I’ll try and fix these, but sorry!
  • I’ve been using an AeroPress to make my coffee of late (though the Chemex’s siren song is wooing me)
  • Lastly, I’m proud to see my top 3 posts are what they are ;)


3 minutes, 17 seconds


I was lucky enough that my work sent me to both visit our office and team of 4 in Nepal, and as well to attend SANOG 27. After submitting my talk on TLS using Let’s Encrypt, I was humbled to have been selected to present as well.




This is my first trip to Nepal and the place is amazing. I’m sad to report that on top of the thousands killed and way more displaced, amazing, ancient sites were heavily damaged in the 2015 earthquake. I visited both Kathmandu Durbar Square and Boudhanath both of which suffered devastating damage.


Thanks to my awesome co-workers, they took me on a motorbike trip to Nagarkot which gave me a chance to get away from the hotel and see something more than nearby Thamel. Kathmandu Valley countryside is beautiful. Though the smog prevented epic views of the Himalayas, staying at the mount side hotel and waking early to see the sunrise was splendid.

On our return ride to Kathmandu, we stopped at Bhaktapur Durbar Square, which suffered much less damage from the quake. The Nyatapola Temple is stunning.





This is my first time attending a Network Operators Group (aka “NOG”) meeting. The bar for future NOGs has been set very high given how amazing SANOG 27 was. The conference, though attaining an all time high over 300 attendees, felt quite small. Given that I was a speaker and staying at the hotel where the conference was, I was also treated almost every night with a dinner paid for by a local sponsor (or not so local in Huawei’s case). There were a couple very sales-centric talks (which is frowned upon), otherwise most of the talks were impressive and informative. I attended them all as there was only one track with all attendees present.


You can see my slides or you can re-watch the live streamed YouTube recording. I was humbled to receive many compliments on my talk, but I feel I have room for improvement!

Special thanks to Fakrul Alam for letting me do a brief Let’s Encrypt demonstration during the Network Security workshop (and also for doing a quick key signing!).

SANOG Workshop


Anyone looking to up their game should seriously consider attending a regional NOG. For example, SANOG 27 was $310 all in: Conference, Tutorial and Workshops with Lunch for all 8 days. Considering flights from the US are well under $1,000, this is quite cheap compared to, say, Black Hat. At over $2,000 for Black Hat, if you took this money to SANOG 27 instead, you would be able to pay for airfare, the full Monty of conference, workshops and tutorials, your hotel AND get a trip to Kathmandu included! I can not underscore enough the level of expertise I saw in the presenters and teachers here. They’re simply amazing.


Pottery Square @ Bhaktapur

Pottery Square @ Bhaktapur

Between both the tourism and conference, here’s my favorites:


NPIX Install

NPIX Install

Thanks to PCH for sending me!

Thanks very much to SANOG 27, Aftab Siddiqui, Gaurab Raj Upadhaya and GZ Kabir for accepting my proposal to speak!

Most of all my thanks to the totally awesome PCH staff who live in the Kathmandu valley. Thank you thank you thank you to Kabindra Shrestha, Chatur Ratna Shakya, Rustan Shrestha, and Dibya Khatiwada. They extended an amazing amount of hospitality and made me feel very welcome at both SANOG and their homeland at large. The best gift a foreigner could ask for is the welcome and help that I received from these four. You are all amazing!

Detecting IPv6 with JS and PHP

0 minutes, 36 seconds

A friend of mine wanted a way to know if visitors to her site were coming from an IPv6 address. To do this, you would run some PHP to output a JS variable with global scope:

// thanks to:
if (substr_count($ip, ":") > 0 && substr_count($ip, ".") == 0) {
        $js = 'var is6 = true';
} else {
        $js = 'var is6 = false';
print "<script>$js</script>";

And then to give the user a sense of excitement, animate showing them if they are v6 or v4. You’ll need jQuery for this, of course:

<div id="ipwhich" style="font-size:2em">?</div>
var showMe = 'v4!';
        var showMe = 'v6!';     

I did up a live demo: give it a try!