Such geek. Wow.https://www.ericlight.com/2022-03-13T22:32:29+13:00An eclectic collection of technical learnings and assorted challenges, for... reasons.task pve-bridge blocked for more than 120 seconds - on Proxmox with MDATP2022-03-13T00:00:00+13:002022-03-13T22:32:29+13:00Eric Lighttag:www.ericlight.com,2022-03-13:/task-pve-bridge-blocked-for-more-than-120-seconds-on-proxmox-with-mdatp.html<p>Today I updated and rebooted a bunch of servers - all in a day's work. Everything went fine, until one of the hosts (the big one) didn't boot up again properly.</p>
<p>I've got two hosts, both running ProxmoxVE (version 7.1) and Microsoft Defender for Endpoint (version 101.61.69-insiderfast). On reboot, one of the hosts came up fine; the other didn't.</p>
<p>Long story short, uninstalling mdatp fixed the problem - wild hypothesis, but I suspect it was interfering with either network bridge or interprocess communication.</p>
<p>The rest of this post is …</p><p>Today I updated and rebooted a bunch of servers - all in a day's work. Everything went fine, until one of the hosts (the big one) didn't boot up again properly.</p>
<p>I've got two hosts, both running ProxmoxVE (version 7.1) and Microsoft Defender for Endpoint (version 101.61.69-insiderfast). On reboot, one of the hosts came up fine; the other didn't.</p>
<p>Long story short, uninstalling mdatp fixed the problem - wild hypothesis, but I suspect it was interfering with either network bridge or interprocess communication.</p>
<p>The rest of this post is technical info for people who might be able to fix it, and so that this blog post will come up for the other people who inevitably bump into this!</p>
<hr>
<p>Symptoms - upon boot, the host came up, was apparently able to launch one VM, and recieved a timeout for all subsequent VM's:</p>
<figure align="center">
<img src="https://www.ericlight.com/images/Tech/mdatp-bridge1.jpg" alt="A screenshot of the failed VM start actions."/>
</figure>
<p>The lines are truncated, but all those pink lines are showing <code>TASK ERROR: start failed: command '/usr/bin/kvm -id 153 [...]' failed: got timeout</code>.</p>
<p>I say 'apparently' launched one VM, because I was unable to interact with it - in fact <strong>all</strong> the launch-on-boot VM's appeared to have booted, except everything about them was non-responsive, including Proxmox stats windows and console.</p>
<p>Trying to manually interact with the VM's using <code>qm</code> failed entirely - the console froze, completely unresponsive to either ^C or ^X, until I forcefully disconnected from SSH.</p>
<p>Checking dmesg revealed a horror story:</p>
<div class="highlight"><pre><span></span><code><span class="go">Mar 13 16:54:36 buckwheat kernel: [ 159.853700] vmbr1: port 1(eth3) entered blocking state</span>
<span class="go">Mar 13 16:54:36 buckwheat kernel: [ 159.853703] vmbr1: port 1(eth3) entered forwarding state</span>
<span class="go">Mar 13 16:54:43 buckwheat kernel: [ 166.700586] ixgbe 0000:81:00.1 eth3: NIC Link is Down</span>
<span class="go">Mar 13 16:54:43 buckwheat kernel: [ 166.701135] vmbr1: port 1(eth3) entered disabled state</span>
<span class="go">Mar 13 16:54:45 buckwheat kernel: [ 168.294208] ixgbe 0000:81:00.1 eth3: NIC Link is Up 10 Gbps, Flow Control: RX/TX</span>
<span class="go">Mar 13 16:54:45 buckwheat kernel: [ 168.294343] vmbr1: port 1(eth3) entered blocking state</span>
<span class="go">Mar 13 16:54:45 buckwheat kernel: [ 168.294349] vmbr1: port 1(eth3) entered forwarding state</span>
<span class="go">Mar 13 16:54:47 buckwheat pvestatd[5040]: VM 112 qmp command failed - VM 112 qmp command 'query-proxmox-support' failed - unable to connect to VM 112 qmp socket - timeout a></span>
<span class="go">Mar 13 16:54:50 buckwheat pvestatd[5040]: VM 105 qmp command failed - VM 105 qmp command 'query-proxmox-support' failed - unable to connect to VM 105 qmp socket - timeout a></span>
<span class="go">Mar 13 16:54:53 buckwheat pvestatd[5040]: VM 115 qmp command failed - VM 115 qmp command 'query-proxmox-support' failed - unable to connect to VM 115 qmp socket - timeout a></span>
<span class="go">Mar 13 16:54:55 buckwheat pve-guests[11257]: start failed: command '/usr/bin/kvm -id 153 -name Eden -no-shutdown -chardev 'socket,id=qmp,path=/var/run/qemu-server/153.qmp,s></span>
<span class="go">Mar 13 16:54:56 buckwheat pvesh[5530]: Starting VM 153 failed: start failed: command '/usr/bin/kvm -id 153 -name Eden -no-shutdown -chardev 'socket,id=qmp,path=/var/run/qem></span>
<span class="go">Mar 13 16:54:56 buckwheat pve-guests[5530]: <root@pam> end task UPID:buckwheat:000015C7:00000710:622D6A6F:startall::root@pam: OK</span>
<span class="go">Mar 13 16:54:56 buckwheat systemd[1]: Finished PVE guests.</span>
<span class="go">Mar 13 16:54:56 buckwheat systemd[1]: Reached target Multi-User System.</span>
<span class="go">Mar 13 16:54:56 buckwheat systemd[1]: Reached target Graphical Interface.</span>
<span class="go">Mar 13 16:54:56 buckwheat systemd[1]: Starting Update UTMP about System Runlevel Changes...</span>
<span class="go">Mar 13 16:54:56 buckwheat systemd[1]: systemd-update-utmp-runlevel.service: Succeeded.</span>
<span class="go">Mar 13 16:54:56 buckwheat systemd[1]: Finished Update UTMP about System Runlevel Changes.</span>
<span class="go">Mar 13 16:54:56 buckwheat systemd[1]: Startup finished in 4.603s (kernel) + 2min 54.823s (userspace) = 2min 59.427s.</span>
<span class="go">Mar 13 16:54:56 buckwheat pvestatd[5040]: VM 104 qmp command failed - VM 104 qmp command 'query-proxmox-support' failed - unable to connect to VM 104 qmp socket - timeout a></span>
<span class="go">Mar 13 16:54:59 buckwheat pvestatd[5040]: VM 153 qmp command failed - VM 153 qmp command 'query-proxmox-support' failed - got timeout</span>
<span class="go">Mar 13 16:54:59 buckwheat pvestatd[5040]: status update time (30.177 seconds)</span>
<span class="go">Mar 13 16:55:18 buckwheat pvestatd[5040]: VM 104 qmp command failed - VM 104 qmp command 'query-proxmox-support' failed - unable to connect to VM 104 qmp socket - timeout a></span>
<span class="go">Mar 13 16:55:21 buckwheat pvestatd[5040]: VM 153 qmp command failed - VM 153 qmp command 'query-proxmox-support' failed - unable to connect to VM 153 qmp socket - timeout a></span>
<span class="go">Mar 13 16:55:24 buckwheat pvestatd[5040]: VM 112 qmp command failed - VM 112 qmp command 'query-proxmox-support' failed - unable to connect to VM 112 qmp socket - timeout a></span>
<span class="go">Mar 13 16:55:27 buckwheat pvestatd[5040]: VM 105 qmp command failed - VM 105 qmp command 'query-proxmox-support' failed - unable to connect to VM 105 qmp socket - timeout a></span>
<span class="go">Mar 13 16:55:30 buckwheat pvestatd[5040]: VM 115 qmp command failed - VM 115 qmp command 'query-proxmox-support' failed - unable to connect to VM 115 qmp socket - timeout a></span>
<span class="go">Mar 13 16:55:30 buckwheat pvestatd[5040]: status update time (30.186 seconds)</span>
<span class="go">Mar 13 16:55:48 buckwheat pvestatd[5040]: VM 153 qmp command failed - VM 153 qmp command 'query-proxmox-support' failed - unable to connect to VM 153 qmp socket - timeout a></span>
<span class="go">Mar 13 16:55:51 buckwheat pvestatd[5040]: VM 104 qmp command failed - VM 104 qmp command 'query-proxmox-support' failed - unable to connect to VM 104 qmp socket - timeout a></span>
<span class="go">Mar 13 16:55:54 buckwheat pvestatd[5040]: VM 115 qmp command failed - VM 115 qmp command 'query-proxmox-support' failed - unable to connect to VM 115 qmp socket - timeout a></span>
<span class="go">Mar 13 16:55:57 buckwheat pvestatd[5040]: VM 105 qmp command failed - VM 105 qmp command 'query-proxmox-support' failed - unable to connect to VM 105 qmp socket - timeout a></span>
<span class="go">Mar 13 16:56:00 buckwheat pvestatd[5040]: VM 112 qmp command failed - VM 112 qmp command 'query-proxmox-support' failed - unable to connect to VM 112 qmp socket - timeout a></span>
<span class="go">Mar 13 16:56:00 buckwheat pvestatd[5040]: status update time (30.191 seconds)</span>
<span class="go">Mar 13 16:56:00 buckwheat kernel: [ 243.301563] INFO: task wdavdaemon:5583 blocked for more than 120 seconds.</span>
</code></pre></div>
<p>The wdavdaemon is shown blocking here, but pve-bridge turned up just as frequently in the logs:</p>
<div class="highlight"><pre><span></span><code><span class="gp">root@buckwheat:/var/log#</span> grep blocked syslog
<span class="go">Mar 13 18:34:14 buckwheat kernel: [ 242.802463] INFO: task wdavdaemon:5740 blocked for more than 120 seconds.</span>
<span class="go">Mar 13 18:34:14 buckwheat kernel: [ 242.802658] INFO: task wdavdaemon:4899 blocked for more than 120 seconds.</span>
<span class="go">Mar 13 18:34:14 buckwheat kernel: [ 242.802840] INFO: task pve-bridge:6117 blocked for more than 120 seconds.</span>
<span class="go">Mar 13 18:34:14 buckwheat kernel: [ 242.802945] INFO: task pve-bridge:7734 blocked for more than 120 seconds.</span>
<span class="go">Mar 13 18:34:14 buckwheat kernel: [ 242.803057] INFO: task pve-bridge:9120 blocked for more than 120 seconds.</span>
<span class="go">Mar 13 18:34:14 buckwheat kernel: [ 242.803170] INFO: task pve-bridge:10283 blocked for more than 120 seconds.</span>
<span class="go">Mar 13 18:36:15 buckwheat kernel: [ 363.631430] INFO: task wdavdaemon:5740 blocked for more than 241 seconds.</span>
<span class="go">Mar 13 18:36:15 buckwheat kernel: [ 363.631610] INFO: task wdavdaemon:4899 blocked for more than 241 seconds.</span>
<span class="go">Mar 13 18:36:15 buckwheat kernel: [ 363.631776] INFO: task pve-bridge:6117 blocked for more than 241 seconds.</span>
<span class="go">Mar 13 18:36:15 buckwheat kernel: [ 363.631872] INFO: task pve-bridge:7734 blocked for more than 241 seconds.</span>
</code></pre></div>
<p>So the interesting thing is that another node - foxtail - was also updated to the same version of both Proxmox and mdatp. The only obvious difference I can see are the numbers of VLANs each of them are bridging to:</p>
<p>This is a list of the bridges now, when they're both working (sorry, Markdown hates tabs; the below should be four tidy columns):</p>
<div class="highlight"><pre><span></span><code><span class="gp">root@foxtail:/var/log#</span> brctl show
<span class="go">bridge name bridge id STP enabled interfaces</span>
<span class="go">fwbr101i0 8000.9e7164f22bab no fwln101i0</span>
<span class="go"> tap101i0</span>
<span class="go">vmbr0 8000.c2602668d5f4 no eno1</span>
<span class="go"> fwpr101p0</span>
<span class="go"> tap100i0</span>
<span class="go"> tap109i0</span>
</code></pre></div>
<p>versus</p>
<div class="highlight"><pre><span></span><code><span class="gp">root@buckwheat:/var/log#</span> brctl show
<span class="go">bridge name bridge id STP enabled interfaces</span>
<span class="go">fwbr102i0 8000.6 abd66965438 no fwln102i0</span>
<span class="go"> tap102i0</span>
<span class="go">fwbr104i0 8000.f60b3f1a3118 no fwln104i0</span>
<span class="go"> tap104i0</span>
<span class="go">fwbr105i0 8000.961281d6d5dc no fwln105i0</span>
<span class="go"> tap105i0</span>
<span class="go">vmbr0 8000.90e2bad572a8 no eth2</span>
<span class="go"> tap112i0</span>
<span class="go"> tap115i0</span>
<span class="go"> tap153i0</span>
<span class="go">vmbr0v5 8000.0ea35ee013ba no eth2.5</span>
<span class="go"> fwpr104p0</span>
<span class="go">vmbr0v666 8000.1a23193ccf17 no eth2.666</span>
<span class="go"> fwpr102p0</span>
<span class="go"> fwpr105p0</span>
<span class="go">vmbr1 8000.90e2bad572a9 no eth3</span>
</code></pre></div>
<p>But when buckwheat was broken, the majority of the bridges were not visible:</p>
<figure align="center">
<img src="https://www.ericlight.com/images/Tech/mdatp-bridge2.jpg" alt="A screenshot of the active bridges on each VM host. Buckwheat is missing a lot."/>
</figure>
<p>At some point during troubleshooting, I restarted pvedaemon - although the service had started correctly, the restart failed with error: <code>timeout waiting on systemd</code>.</p>Goldenhorse - Wake Up Brother bass tab2022-02-19T00:00:00+13:002022-02-19T22:42:48+13:00Eric Lighttag:www.ericlight.com,2022-02-19:/goldenhorse-wake-up-brother-bass-tab.html<p>I know Goldenhorse didn't get particularly huge, but I always really enjoyed their work. Wake Up Brother is one of those ones that really feels like an achievable song for a small band - it's got solid, driving bass; a groovy bright guitar line; and requires quite a dynamic singer to pull it off.</p>
<p>Some friends and I are planning to add it to our band's repertoire, but the bassline is a bit too complex for us to transcribe properly. And the song wasn't particularly well-known, so there's really only one …</p><p>I know Goldenhorse didn't get particularly huge, but I always really enjoyed their work. Wake Up Brother is one of those ones that really feels like an achievable song for a small band - it's got solid, driving bass; a groovy bright guitar line; and requires quite a dynamic singer to pull it off.</p>
<p>Some friends and I are planning to add it to our band's repertoire, but the bassline is a bit too complex for us to transcribe properly. And the song wasn't particularly well-known, so there's really only one public bass tab, and it wasn't really comprehensive enough... So I turned to Fiverr!</p>
<p>There are a bunch of folks there who will transcribe bass tab - but one of them stuck out to me, so I decided to work with <a href="https://www.fiverr.com/georgex0006">georgex0006</a>.</p>
<p>I was <em>super</em> impressed with his speed and quality of work. I never could have nailed the bassline as well as he did, and providing a playalong video as well is 100% awesome.</p>
<p>I'm sharing the bass tab and playalong here, with his permission. If you need someone to do some bass tab for you, please give him your support!</p>
<ul>
<li>Tab & score <a href="https://www.ericlight.com/files/Wake-up-brother.pdf">PDF Version here</a></li>
<li>Playalong <a href="https://www.ericlight.com/files/Wake-up-brother.mp4">MP4 Version here</a></li>
</ul>
<p>And for my personal use (and yours, if you own the album), I purchased a .FLAC of the track which is stored <a href="https://www.ericlight.com/files/Goldenhorse-WakeUpBrother.flac">here</a>. However if you don't already own it, please pay for it yourself first, or listen to it on <a href="https://www.youtube.com/watch?v=RgFl4CpBX8U">YouTube</a> where they can deal with copyright issues.</p>Seltzer brewing2021-12-12T00:00:00+13:002022-03-12T00:00:00+13:00Eric Lighttag:www.ericlight.com,2021-12-12:/seltzer-brewing.html<p>I got into brewing seltzer during the spring of 2021, and these are my notes. They're in descending order, so the most-recent are at the top. The notes got progressively less-detailed as time went by, so those looking to actually learn things (e.g. "How much yeast nutrient should I use in a seltzer that's 100% dextrose") should read the highlights and then read from bottom-up. :)</p>
<h1>Highlights:</h1>
<ul>
<li>Kveik Voss is fast-fermenting and relatively transparent flavour. Excellent for seltzer</li>
<li>It does take a couple days post-fining for the yeast scent to …</li></ul><p>I got into brewing seltzer during the spring of 2021, and these are my notes. They're in descending order, so the most-recent are at the top. The notes got progressively less-detailed as time went by, so those looking to actually learn things (e.g. "How much yeast nutrient should I use in a seltzer that's 100% dextrose") should read the highlights and then read from bottom-up. :)</p>
<h1>Highlights:</h1>
<ul>
<li>Kveik Voss is fast-fermenting and relatively transparent flavour. Excellent for seltzer</li>
<li>It does take a couple days post-fining for the yeast scent to diminish</li>
<li>Recycling yeast is tricky with seltzer due to all the fruit sediment</li>
<li>With only sugars and fruit flesh, yeast nutrient is essential - about 15 grams seems to do the trick</li>
<li>One kg of dextrose in 19 litres will raise the ABV by approximately 2.65%</li>
<li>Don't boil the fruit or you'll get pectin haze; raise it to about 75°C to sterilise it, though</li>
<li>Table sugar is a perfectly passable sugar; make invert sugar by boiling it with a little citric acid, 20-60 minutes</li>
<li>Citric acid is <em>amazing</em></li>
</ul>
<h1>Fruit notes:</h1>
<ul>
<li>Mashing the fruit a little bit is a significant factor in releasing the fruit flavours</li>
<li>Lychee have quite a prominent character, good to pair with something that can compete</li>
<li>Mandarins will impart <em>very</em> little flavour unless you mash them really good pre-ferment</li>
<li>Jackfruit is almost undetectable, even with two cans; will try blending next time</li>
<li>Pineapple seems to digest(?) other fruits. The other fruit becomes quickly less-noticable while the pineapple becomes more prominent</li>
<li>Raspberries create a visually beautiful brew, as do plums</li>
<li>Passionfruit pulp is pretty disappointing; in brew #7 I used THREE cans, and it was nearly undetectable</li>
<li>Mango is pretty awful, really - lots of fruit mush, lots of haze, some weird aged-fruit flavour... avoid imho</li>
</ul>
<h1>Yeast Awakener</h1>
<p>To reawaken the yeast from the fridge, I make a mix of:</p>
<ul>
<li>A tablespoon of sugar (any variety, often dextrose)</li>
<li>10 grams chopped raisins OR 2tsp lemon juice</li>
<li>6 grams Marmite</li>
<li>Pinch of yeast nutrient</li>
</ul>
<p>Once those are dissolved together, I pour in collected yeast from the previous batch.</p>
<h1>Other thoughts:</h1>
<ul>
<li>2022-01-04 - my brews are still coming out very sweet - I'm yearning for something with a dryer character. Hard seltzer was featured in an exBEERiment on Brulosophy on the <a href="https://brulosophy.com/2021/03/22/hard-seltzer-sucrose-vs-dextrose-exbeeriments-results/">difference between dextrose and sucrose</a> (it seems table sugar will be fine!), where Phil mentions using the W04 Paramount wine yeast(!), along with 32g of yeast nutrient(!!). Perhaps this will solve my sweet brews? Might also get my water acidity tested to make sure it's at a good pH for the fermentation.</li>
<li>2022-01-21 - the increased yest nutrient is working out very well; much cleaner and dryer - 25g seems good. Ordered some Fermaid AT today as well to see if a slower release of yeast-available nitrogen (YAN) will support the yeast better</li>
</ul>
<hr>
<h1>Recipes and notes</h1>
<h3>Brew #11, 2022-03-12 - brewing: Blueberry and Mandarin Seltzer - large edition</h3>
<p><strong>Recipe:</strong></p>
<ul>
<li>3kg invert table sugar</li>
<li>10g Citric acid</li>
<li>15g+15g Fermaid-AT</li>
<li>Kveik Voss</li>
<li>310g tinned mandarins</li>
<li>1275g tinned blueberries</li>
</ul>
<p><strong>Notes:</strong></p>
<ul>
<li>Decided it was high time to brew a larger batch - this is a 25 litre brew</li>
<li>The citric acid has been amazing - boosted the quantity in this one to compensate for the larger proportion of fruit</li>
<li>Dosed 15g of Fermaid-AT at inital brew; will dose another 15g at 3 days</li>
<li>Looking to try some amylase enzyme to see if I can really dry out the seltzer</li>
</ul>
<h3>Brew #10, 2022-02-20 - 2022-02-28: Blueberry and Mandarin Seltzer</h3>
<p><strong>Recipe:</strong></p>
<ul>
<li>2kg white table sugar (see notes)</li>
<li>5g Citric acid</li>
<li>10g+10g yeast nutrient (Fermaid-AT)</li>
<li>A fresh Kveik Voss</li>
<li>310g tinned mandarins</li>
<li>850g tinned blueberries</li>
</ul>
<p><strong>Notes:</strong></p>
<ul>
<li>My Fermaid-AT has arrived! It's used at a rate up to 1g/l in low-YAN environments, so used 10g and will add another 10g in 2 days</li>
<li>Two batches of 10g FermaidAT was pretty good, the Kveik chews that stuff up super-quick, literally over 36 hours</li>
<li>I really liked this combination so revisiting the double-blueberry and mandarin with a couple tweaks</li>
<li>The invert sugar experiment seemed to be a success, so 2kg table sugar + 5g citric acid; boil for 20mins</li>
<li>Easily one of my favourites - possibly <strong>THE</strong> favourite - so far. 4/5, only minor improvements</li>
<li>Update, citric acid is <em>amazing</em>, absolutely brings the zing that I was craving. Still getting sweet brews but much more balanced now</li>
<li>Next brew will try 15g+10g nutrient</li>
</ul>
<h3>Brew #9, 2022-01-26 - 2022-02-01: Apple, Mango, and Guava Seltzer</h3>
<p><strong>Recipe:</strong></p>
<ul>
<li>2kg white table sugar (see notes)</li>
<li>4g Citric acid</li>
<li>23g yeast nutrient</li>
<li>My weird hybrid yeast now (see notes)</li>
<li>1kg diced apple</li>
<li>410g tinned guava</li>
<li>850g mango pulp</li>
</ul>
<p><strong>Notes:</strong></p>
<ul>
<li>I ran out of yeast nutrient so only 23g this time</li>
<li>Overshot water, but had lots more fruit than normal so this is a 24l batch</li>
<li>Decided to attempt invert sugar instead of dextrose! 2kg table sugar + 4g citric acid; boil for 20mins</li>
<li>The Kveik Voss + Mangrove Jack's Seltzer yeast is doing the job very nicely</li>
<li>Initial flavour suggests this might be a goodie.</li>
<li>Final flavour - meh. 2/5, I wouldn't brew this again. The citric acid seemed to be a good call though.</li>
</ul>
<h3>Brew #8, 2022-01-16 - 2022-01-21: Blueberry and Mandarin Seltzer</h3>
<p><strong>Recipe:</strong></p>
<ul>
<li>1.7kg Dextrose, 300g white sugar</li>
<li>Kveik Voss plus Mangrove Jacks' Seltzer yeast</li>
<li>25g yeast nutrient</li>
<li>310g tinned mandarins</li>
<li>850g tinned blueberries</li>
</ul>
<p><strong>Notes:</strong></p>
<ul>
<li>Previous run went very well (much drier result), so bumped nutrient to 25g! </li>
<li>Recycled the Kveik Voss + MJ's Seltzer yeast from last batch; seemed pretty okay</li>
<li>Result - an absolute banger! Really delicious; next time I'll replace the mandarin with something more acidic though</li>
</ul>
<h3>Brew #7, 2022-01-05 - 2022-01-10: Pineapple Passion Seltzer</h3>
<p><strong>Recipe:</strong></p>
<ul>
<li>2kg Dextrose</li>
<li>Kveik Voss plus Mangrove Jacks' Seltzer yeast</li>
<li>20g yeast nutrient</li>
<li>420g tinned crushed pineapple</li>
<li>510g tinned passionfruit pulp</li>
</ul>
<p><strong>Notes:</strong></p>
<ul>
<li>Increased yeast nutrient to 20g this time, will see if it makes a difference. (Update - huge difference!)</li>
<li><em>Probably</em> made a mistake with my yeast. I'd started up some Mangrove Jacks' seltzer yeast to try... but then remembered how slow it is, so I pitched some fresh Kviek on top of it. Eek... I expect the Seltzer yeast to create some off flavours at 36°</li>
<li>Also made a mistake with the yeast nutrient - I completely forgot it until the fermenter was already in the fridge! Boiled some up and added it in, hopefully it doesn't really need much boiling.</li>
<li>Result - this one wasn't a winner for me. It was dry like I wanted, but the passionfruit was a big disappointment</li>
</ul>
<h3>Brew #6, 2021-12-28 - 2022-01-02: Plum, Pineapple, and Mandarin Seltzer</h3>
<p><strong>Recipe:</strong></p>
<ul>
<li>2kg Dextrose</li>
<li>Kveik Voss yeast</li>
<li>14g yeast nutrient</li>
<li>850g tinned Black Doris plums</li>
<li>420g tinned crushed pineapple</li>
<li>310g tinned mandarins</li>
</ul>
<p><strong>Notes:</strong></p>
<ul>
<li>Thoroughly crushed the plums and mandarins with the back of a fork this time</li>
<li>Had real trouble reinvigorating the yeast from the previous brew; might need to order a spare yeast for backup</li>
<li>10% Brix at start; finished just under 8% Brix... if this refractometer is accurate, these are very low ABV</li>
<li>Result - this was absolutely one of my favourites. Great outcome!</li>
</ul>
<h3>Brew #5, 2021-12-21 - 2021-12-25: Pineapple and Double Raspberry Seltzer</h3>
<p><strong>Recipe:</strong></p>
<ul>
<li>2kg Dextrose</li>
<li>Kveik Voss yeast</li>
<li>16g yeast nutrient</li>
<li>850g tinned Raspberries</li>
<li>420g tinned crushed pineapple</li>
</ul>
<p><strong>Notes:</strong></p>
<ul>
<li>Visually beautiful, great nose, and quite refreshingly delightful to drink.</li>
<li>The acidity of the raspberry and pineapple combined made this taste much like a kombucha. Weird.</li>
<li>Failed to take any gravity readings.</li>
</ul>
<h3>Brew #4, 2021-12-12 - 2021-12-17: Black Doris Plum and Pineapple Seltzer</h3>
<p><strong>Recipe:</strong></p>
<ul>
<li>2kg Dextrose</li>
<li>Kveik Voss yeast</li>
<li>12g yeast nutrient</li>
<li>850g tinned Black Doris plums</li>
<li>850g tinned pineapple (half crushed; half chunks)</li>
</ul>
<p><strong>Notes:</strong></p>
<ul>
<li>Initial tasting is very much drier than the others - not sure if this was the acids in the pineapple cutting the sugar, or if the sugar syrup in the cans was way thinner? Either way, this may end up a low percentage.</li>
<li>Original brix reading looked to be about 7%, suggesting an expected ABV of only 3.6%</li>
<li>(later): turns out I have no idea how refractometers work. Never mind.</li>
<li>This recipe came out <em>amazing</em>, absolutely delicious. Started out with a fairly subtle plum flavour, with the pineapple just becoming perceptible at the end.</li>
<li>However, during the week the plum flavour diminished and the pineapple flourished. This continued to the point where it was actually really unbalanced; I suspect it was caused by enzymes in the pineapple... to combat this, next time I'll use only one tin.</li>
</ul>
<h3>Brew #3, 2021-12-04 - 2021-12-10: Lychee and Jackfruit Seltzer</h3>
<p><strong>Recipe:</strong></p>
<ul>
<li>1.2kg Dextrose, plus other assorted sugars to 2kg (approx 5.3%)</li>
<li>Kveik Voss yeast</li>
<li>16g yeast nutrient</li>
<li>850g tinned jackfruit</li>
<li>560g tinned lychee</li>
</ul>
<p><strong>Notes:</strong></p>
<ul>
<li>Brewing out much quicker now with the increased nutrient</li>
<li>Lychee is very prominent in finished product. Not overwhelming but definitely star of the show</li>
<li>Jackfruit brings very little flavour. Next time I might blend it up but worried about post-brew yeast collection</li>
</ul>
<h3>Brew #3, 2021-11-26 - 2021-12-03: Double Raspberry and Mandarin Seltzer</h3>
<p><strong>Recipe:</strong></p>
<ul>
<li>2kg Dextrose (for approx 5.3%)</li>
<li>Kveik Voss yeast</li>
<li>16g yeast nutrient</li>
<li>820g tinned raspberries</li>
<li>310g tinned mandarins</li>
</ul>
<p><strong>Notes:</strong></p>
<ul>
<li>Doubled the raspberry; reduced the dextrose; tripled the yeast nutrient</li>
<li>Raspberry far more prominent and yum. Zero impact from mandarin</li>
<li>Yeast nutrient really helped. Still a bit sweet but far better; probably no need to change</li>
<li>Adding the dextrose, plus approximate sugar syrup and fruit sugars, suggests a 6% ABV</li>
</ul>
<h3>Brew #2, 2021-11-17 to 2021-11-24: Raspberry and Mandarin Seltzer</h3>
<p><strong>Recipe:</strong></p>
<ul>
<li>2.5kg Dextrose (for approx 6%)</li>
<li>Kveik Voss yeast</li>
<li>5g yeast nutrient</li>
<li>410g tinned raspberries</li>
<li>310g tinned mandarins</li>
</ul>
<p><strong>Method:</strong></p>
<ul>
<li>Filled keg to 12l line with tap water</li>
<li>2.5kg Dextrose + 6g nutrient into 3 litres of water. Heated to 80°C</li>
<li>Took off heat, added tin of raspberries and tin of mandarins, including syrup; mashed up a bit</li>
<li>Brought temp back up to 75°C, and poured it into 16 litres of room temp water</li>
<li>Pitched Kveik yeast at 29°C. Total 20 litres ish, fermenting at 32°C</li>
</ul>
<p><strong>Notes:</strong></p>
<ul>
<li>Brew finished on 2021-11-24, exactly a week later</li>
<li>Kveik ferments much quicker, and very clean; happy</li>
<li>Mandarin very subtle, raspberry present but light. Still delicious</li>
<li>Didn't add enough yeast nutrient!! Extremely sweet, but yeast has gone mostly dormant</li>
<li>Forgot to account for sugars from fruits; happy the yeast went to sleep before I got rocket fuel</li>
</ul>
<h3>Brew #1, 2021-10-25 to 2021-11-12: <a href="https://mangrovejacks.com/products/pineapple-sunset-hard-seltzer">Mangrove Jack's Pineapple Sunset Hard Seltzer</a></h3>
<p>Brewed as per instructions, but added 12g of <a href="https://mangrovejacks.com/collections/consumables/products/natural-beer-flavour-boost-passionfruit">Mangrove Jack's Passionfruit</a> Beer flavour boost.
Fermented a little slow; took a bit over two weeks to finish</p>
<p><strong>Tasting notes:</strong></p>
<ul>
<li>Came out with the same acrid/chemical flavour that many others complain about</li>
<li>Brewing process super simple, though. Think I can do this myself without a kit</li>
</ul>Acronis Cyber Protect and Microsoft Defender on the same Linux system2021-11-07T00:00:00+13:002021-11-07T12:53:20+13:00Eric Lighttag:www.ericlight.com,2021-11-07:/acronis-cyber-protect-and-microsoft-defender-on-the-same-linux-system.html<p>A few months ago, I <a href="https://www.ericlight.com/microsoft-defender-for-endpoint-mdatp-on-debian-sid.html">published what I learned</a> from playing with the Linux version of <a href="https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/microsoft-defender-endpoint-linux?view=o365-worldwide">Microsoft Defender for Endpoint</a> a few months back. If you're here, you'll have possibly already read my original post. There was a bit of tuning required to get it to behave nicely; just adding some sensible audit logging exclusions. </p>
<p>Well the Acronis Cyber Protect backup platform has recently been added to the bundle, and it had a few specific requirements, so I've documented them here.</p>
<p>There are four Acronis processes which MDATP will spend …</p><p>A few months ago, I <a href="https://www.ericlight.com/microsoft-defender-for-endpoint-mdatp-on-debian-sid.html">published what I learned</a> from playing with the Linux version of <a href="https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/microsoft-defender-endpoint-linux?view=o365-worldwide">Microsoft Defender for Endpoint</a> a few months back. If you're here, you'll have possibly already read my original post. There was a bit of tuning required to get it to behave nicely; just adding some sensible audit logging exclusions. </p>
<p>Well the Acronis Cyber Protect backup platform has recently been added to the bundle, and it had a few specific requirements, so I've documented them here.</p>
<p>There are four Acronis processes which MDATP will spend a lot of time scanning and rescanning. Exclude those from the scanning engine by executing the following commands as root:</p>
<div class="highlight"><pre><span></span><code>mdatp exclusion process add --path /usr/lib/Acronis/Schedule/schedul2-bin
mdatp exclusion process add --path /usr/lib/Acronis/APL/active-protection
mdatp exclusion process add --path /opt/acronis/aakore
mdatp exclusion process add --path /usr/lib/Acronis/BackupAndRecovery/mms
</code></pre></div>
<p>There are also five processes which need to be excluded from auditctl, unless you want your audit logs rotated every ten minutes. Again, these must all be run as root.</p>
<div class="highlight"><pre><span></span><code><span class="nb">echo</span> -a never,exit -S <span class="m">41</span> -S <span class="m">42</span> -F <span class="nv">comm</span><span class="o">=</span><span class="s2">"mms"</span> -k exclude_acronis >> /etc/audit/rules.d/01-exclusion.rules
<span class="nb">echo</span> -a never,exit -S <span class="m">41</span> -S <span class="m">42</span> -S <span class="m">43</span> -F <span class="nv">comm</span><span class="o">=</span><span class="s2">"adp-agent"</span> -k exclude_acronis >> /etc/audit/rules.d/01-exclusion.rules
<span class="nb">echo</span> -a never,exit -S <span class="m">41</span> -S <span class="m">42</span> -S <span class="m">43</span> -S <span class="m">288</span> -F <span class="nv">exe</span><span class="o">=</span>/usr/lib/Acronis/APL/active-protection -k exclude_acronis >> /etc/audit/rules.d/01-exclusion.rules
<span class="nb">echo</span> -a never,exit -S <span class="m">41</span> -S <span class="m">42</span> -S <span class="m">43</span> -F <span class="nv">exe</span><span class="o">=</span>/opt/acronis/bin/updater -k exclude_acronis >> /etc/audit/rules.d/01-exclusion.rules
<span class="nb">echo</span> -a never,exit -S <span class="m">41</span> -S <span class="m">42</span> -S <span class="m">288</span> -F <span class="nv">exe</span><span class="o">=</span>/opt/acronis/aakore -k exclude_acronis >> /etc/audit/rules.d/01-exclusion.rules
</code></pre></div>
<p>Once you've created the exclusions, you can either reboot or run <code>service auditd restart</code>. Either way, make sure you run <code>service auditd status</code> to ensure nothing went wrong with the exclusions.</p>Microsoft Defender for Endpoint (mdatp) on Debian Sid2021-07-07T00:00:00+12:002021-08-01T00:00:00+12:00Eric Lighttag:www.ericlight.com,2021-07-07:/microsoft-defender-for-endpoint-mdatp-on-debian-sid.html<p><strong> 2021-08-01 Update: </strong> </p>
<p>This is a better string to find out what's hitting your audit log: <code>cat /var/log/audit/audit.log* | cut -d ' ' -f26 | sort | uniq -c | sort -n | tail -n 6 | head -n5</code></p>
<hr>
<p>Linux doesn't have many great antivirus options available. </p>
<p>Don't get me wrong, there are actually a few options nowadays. We've got the ever-present <a href="https://www.clamav.net/">ClamAV</a>; <a href="https://www.bitdefender.com">BitDefender</a> has a good reputation, but I haven't played with it yet; <a href="https://www.sophos.com/en-us/support/documentation/sophos-anti-virus-for-linux.aspx?">Sophos AV</a> for Linux <em>seems</em> to be in limbo. <a href="https://www.eset.com/int/home/antivirus-linux/">ESET for Linux</a> exists, as does <a href="https://techdocs.broadcom.com/us/en/symantec-security-software/endpoint-security-and-management/endpoint-protection/all/getting-up-and-running-on-for-the-first-time-v45150512-d43e1033/installing-clients-with-save-package-v16194723-d21e1502/installing-the-client-for-linux-v95193124-d21e2986.html">Symantec Endpoint Protection</a> for Linux …</p><p><strong> 2021-08-01 Update: </strong> </p>
<p>This is a better string to find out what's hitting your audit log: <code>cat /var/log/audit/audit.log* | cut -d ' ' -f26 | sort | uniq -c | sort -n | tail -n 6 | head -n5</code></p>
<hr>
<p>Linux doesn't have many great antivirus options available. </p>
<p>Don't get me wrong, there are actually a few options nowadays. We've got the ever-present <a href="https://www.clamav.net/">ClamAV</a>; <a href="https://www.bitdefender.com">BitDefender</a> has a good reputation, but I haven't played with it yet; <a href="https://www.sophos.com/en-us/support/documentation/sophos-anti-virus-for-linux.aspx?">Sophos AV</a> for Linux <em>seems</em> to be in limbo. <a href="https://www.eset.com/int/home/antivirus-linux/">ESET for Linux</a> exists, as does <a href="https://techdocs.broadcom.com/us/en/symantec-security-software/endpoint-security-and-management/endpoint-protection/all/getting-up-and-running-on-for-the-first-time-v45150512-d43e1033/installing-clients-with-save-package-v16194723-d21e1502/installing-the-client-for-linux-v95193124-d21e2986.html">Symantec Endpoint Protection</a> for Linux. That's a pretty decent range - but they each have some real drawback. Assuming the price is right, you still see compatibility, usability, licensing dramas, or resource drain challenges.</p>
<p>Most recently, the Linux version of <a href="https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/microsoft-defender-endpoint-linux?view=o365-worldwide">Microsoft Defender for Endpoint</a> entered the playing field. I finally got to play with this and I gotta say...</p>
<p><em>Holy shit.</em></p>
<p>Look, I know we enjoy ragging on Microsoft. They've demonstrated some awful behaviour over the years, and every action still harkens back to the "Embrace, Extend, Extinguish" <em>modus operandi</em>. But they're doing really great work with the Defender/DATP/MDFE/whatever line. Even the basic Defender has been steading climbing the ranks, to the point where virtually <em>all</em> guidance I've heard for the last two years is: "if you're not going full EDR, just use regulr Defender". It's no SentinelOne or CrowdStrike, but overall Defender just Gets The Job Done.</p>
<p>So, I was excited to try the Linux version. Long story short, it was a dream. The installation process was <em>streaks ahead</em> of the competition. Resource usage is generally negligible, adding an average load of around 0.5% CPU, going up to about 16% CPU during a scan. There's a robust health and connectivity test built-in. Basically the whole thing just works, to the same level we've learned to expect from the Windows version. Oh and this one has <strong>actual documentation</strong> which seems to be considered optional by some of the competitors. 🙃</p>
<p>However.</p>
<p>You may find that mdatp is frantically scanning files that freqently Do Things. Bind9 (named) for example, might be handling hundreds of queries a minute. Each one of them triggers <em>not only</em> an mdatp scan, but also auditd entries... which often logs more than once per query. I was finding logs being filled and rotated <strong>every seven minutes</strong> in some cases... and then punctuated by auditd yelling "my buffer is full, I can't log all these events!".</p>
<p>So as a result, I've spent quite a few hours learning how to wrangle auditd around exclusions. Here's what I've learned:</p>
<h1>You need to lie to install MDFE on Sid</h1>
<p>Edit <code>/etc/os-release</code> and change <code>VERSION_ID="11"</code> to <code>VERSION_ID="10"</code>. After that, you can install MDFE following the regular instructions. Don't forget to change it back later! </p>
<h1>Troubleshooting performance issues:</h1>
<p><em>See also: <a href="https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/linux-support-perf?view=o365-worldwide">https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/linux-support-perf?view=o365-worldwide</a></em></p>
<p>First step - find the processes that mdatp is spending the most CPU time on:</p>
<div class="highlight"><pre><span></span><code><span class="c1"># Download Microsoft's parser (only do this once)</span>
wget -c https://raw.githubusercontent.com/microsoft/mdatp-xplat/master/linux/diagnostic/high_cpu_parser.py
<span class="c1"># Ask Defender to output the stats, and then parse it looking for high CPU:</span>
$ mdatp diagnostic real-time-protection-statistics --output json <span class="p">|</span> python high_cpu_parser.py
<span class="m">925</span> mongodb <span class="m">29184</span>
<span class="m">37575</span> pulseaudio <span class="m">47</span>
<span class="m">21355</span> packagekitd <span class="m">30</span>
<span class="m">37588</span> dbus-daemon <span class="m">26</span>
<span class="m">37550</span> sshd <span class="m">25</span>
</code></pre></div>
<p>... Yikes, it's probably not necessary to scan MongoDB thirty thousand times! You can exclude a process from mdatp like this: <code>sudo mdatp exclusion process add --path /usr/bin/mongod</code></p>
<p>But that's not all... even though mdatp is no longer <strong>scanning</strong> the application, you still have auditd frantically logging <em>every single thing it does</em>. That's also going to cause periodic slowdowns as the auditd buffer fills up, overflows, panicks, and then purges the stuff it couldn't write down.</p>
<h2>Syslog/audit logging issues</h2>
<p>You can find out if anything is spewing a billion entries into your audit log, by just grepping for the rotation in syslog:</p>
<div class="highlight"><pre><span></span><code><span class="c1"># grep 'Audit daemon rotating' /var/log/syslog</span>
Jul <span class="m">6</span> <span class="m">01</span>:00:08 spam auditd<span class="o">[</span><span class="m">28996</span><span class="o">]</span>: Audit daemon rotating log files
Jul <span class="m">6</span> <span class="m">04</span>:00:05 spam auditd<span class="o">[</span><span class="m">28996</span><span class="o">]</span>: Audit daemon rotating log files
Jul <span class="m">6</span> <span class="m">06</span>:57:01 spam auditd<span class="o">[</span><span class="m">28996</span><span class="o">]</span>: Audit daemon rotating log files
Jul <span class="m">6</span> <span class="m">09</span>:57:18 spam auditd<span class="o">[</span><span class="m">28996</span><span class="o">]</span>: Audit daemon rotating log files
</code></pre></div>
<p>... Filling up a log file every three hours is <em>weird</em>, but previously this server was doing it every few minutes. You can see what's causing all the log rotations with:</p>
<div class="highlight"><pre><span></span><code><span class="c1"># cat /var/log/audit/audit.log* | cut -d ' ' -f26 | sort | uniq -c</span>
<span class="m">138581</span>
<span class="m">1</span> <span class="nv">exe</span><span class="o">=</span><span class="s2">"/bin/bash"</span>
<span class="m">4</span> <span class="nv">exe</span><span class="o">=</span><span class="s2">"/bin/hostname"</span>
<span class="m">2</span> <span class="nv">exe</span><span class="o">=</span><span class="s2">"/bin/nano"</span>
<span class="m">684</span> <span class="nv">exe</span><span class="o">=</span><span class="s2">"/lib/systemd/systemd"</span>
<span class="m">4754</span> <span class="nv">exe</span><span class="o">=</span><span class="s2">"/lib/systemd/systemd-logind"</span>
<span class="m">209</span> <span class="nv">exe</span><span class="o">=</span><span class="s2">"/lib/systemd/systemd-user-runtime-dir"</span>
<span class="m">119</span> <span class="nv">exe</span><span class="o">=</span><span class="s2">"/opt/microsoft/mdatp/sbin/osqueryi"</span>
<span class="m">9</span> <span class="nv">exe</span><span class="o">=</span><span class="s2">"/usr/bin/apt-get"</span>
<span class="m">2133</span> <span class="nv">exe</span><span class="o">=</span><span class="s2">"/usr/bin/dbus-daemon"</span>
<span class="m">13212</span> <span class="nv">exe</span><span class="o">=</span><span class="s2">"/usr/bin/perl"</span>
<span class="m">10784</span> <span class="nv">exe</span><span class="o">=</span><span class="s2">"/usr/bin/pmxcfs"</span>
<span class="m">14</span> <span class="nv">exe</span><span class="o">=</span><span class="s2">"/usr/bin/rrdcached"</span>
<span class="m">2</span> <span class="nv">exe</span><span class="o">=</span><span class="s2">"/usr/bin/sort"</span>
<span class="m">4</span> <span class="nv">exe</span><span class="o">=</span><span class="s2">"/usr/lib/postfix/sbin/cleanup"</span>
<span class="m">880</span> <span class="nv">exe</span><span class="o">=</span><span class="s2">"/usr/lib/postfix/sbin/pickup"</span>
<span class="m">175</span> <span class="nv">exe</span><span class="o">=</span><span class="s2">"/usr/lib/postfix/sbin/qmgr"</span>
<span class="m">27</span> <span class="nv">exe</span><span class="o">=</span><span class="s2">"/usr/lib/postfix/sbin/smtp"</span>
<span class="m">4</span> <span class="nv">exe</span><span class="o">=</span><span class="s2">"/usr/lib/postfix/sbin/trivial-rewrite"</span>
<span class="m">16</span> <span class="nv">exe</span><span class="o">=</span><span class="s2">"/usr/sbin/cron"</span>
<span class="m">10326</span> <span class="nv">exe</span><span class="o">=</span><span class="s2">"/usr/sbin/ebtables-legacy"</span>
<span class="m">10326</span> <span class="nv">exe</span><span class="o">=</span><span class="s2">"/usr/sbin/ebtables-legacy-restore"</span>
<span class="m">3</span> <span class="nv">exe</span><span class="o">=</span><span class="s2">"/usr/sbin/postdrop"</span>
<span class="m">5</span> <span class="nv">exe</span><span class="o">=</span><span class="s2">"/usr/sbin/qmeventd"</span>
<span class="m">2</span> <span class="nv">exe</span><span class="o">=</span><span class="s2">"/usr/sbin/sendmail"</span>
<span class="m">56</span> <span class="nv">exe</span><span class="o">=</span><span class="s2">"/usr/sbin/smartd"</span>
<span class="m">3255</span> <span class="nv">exe</span><span class="o">=</span><span class="s2">"/usr/sbin/sshd"</span>
</code></pre></div>
<p>The number on the left shows the number of times that binary has had it's activity logged. This should clearly show the problem executables... today we're looking at <code>perl</code>, <code>pmxcfs</code>, and <code>ebtables-legacy</code>. Once you've got that, you need to determine which <em>syscalls</em> are part of regular noise:</p>
<div class="highlight"><pre><span></span><code><span class="c1"># grep /usr/bin/pmxcfs /var/log/audit/audit.log* | cut -d ' ' -f 4 | sort | uniq -c</span>
<span class="m">10856</span>
<span class="m">8142</span> <span class="nv">syscall</span><span class="o">=</span><span class="m">263</span>
<span class="m">1357</span> <span class="nv">syscall</span><span class="o">=</span><span class="m">43</span>
<span class="m">1357</span> <span class="nv">syscall</span><span class="o">=</span><span class="m">84</span>
</code></pre></div>
<p>Referring to <a href="https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/">this document</a>, we can see these syscalls are sys_accept, sys_rmdir, and sys_unlinkat. Since pmxcfs is the ProxmoxVS Cluster File System, these are frankly all pretty normal syscalls for it to make. Let's ignore them.</p>
<p><code>echo -a never,exit -S 43 -S 84 -S 263 -F exe=/usr/bin/pmxcfs -k exclude_PVE_internals >> /etc/audit/rules.d/01-exclusion.rules</code></p>
<p>^ Gotta do that as root, btw, or just append the line however you see fit. Once you've added exclusions for all of your high-noise entires, run <code>service auditd restart</code> and then <code>service auditd status</code> to make sure it worked properly.</p>
<p>On my Zentyal box I had to add a bunch of entries to exclude logging of certain high-noise things. For example, DNS query resolution (via named) and Samba activity:</p>
<div class="highlight"><pre><span></span><code>cat /etc/audit/rules.d/01-exclusion.rules
-a never,exit -S 41 -S 42 -S 49 -S 82 -S 288 -F exe=/usr/sbin/named -k exclude_DNS_queries
-a never,exit -S 43 -F exe=/usr/sbin/winbindd -k exclude_Samba
-a never,exit -S 41 -S 42 -S 43 -S 87 -F exe=/usr/sbin/smbd -k exclude_Samba
-a never,exit -S 41 -S 43 -S 87 -F exe=/usr/sbin/samba -k exclude_Samba
</code></pre></div>
<p><strong>A word of warning:</strong> Don't just ignore everything willy-nilly. The audit logging system <em>exists</em> so you can track activity on the system - blithely sending 100% of the log entries to the bin will undermine what the audit sytem exists for!</p>
<p>... That's all I've got so far. I'll keep updating this if I bump into anything new!</p>Recipe: Bangin' Satay2021-05-24T00:00:00+12:002021-05-24T20:23:09+12:00Eric Lighttag:www.ericlight.com,2021-05-24:/recipe-bangin-satay.html<p>Had a hankering for a Satay Chicken tonight and kinda whipped something up based on a couple different things. This is more of a saucy satay, not a dry skewer-type. This takes a bit of juggling; I had three elements on the stove, and a few stages. Worth it, tho.</p>
<p>I've broken this into stages: the sauce, the veggies, and the noodles. For the benefit of shopping lists (and Whisk!) I've provided an awful monolithic pile of ingredients up-front. Yay.</p>
<h2>Ingredients</h2>
<ul>
<li>2 large chicken breasts</li>
<li>2 Tbsp fish sauce</li>
<li>2 …</li></ul><p>Had a hankering for a Satay Chicken tonight and kinda whipped something up based on a couple different things. This is more of a saucy satay, not a dry skewer-type. This takes a bit of juggling; I had three elements on the stove, and a few stages. Worth it, tho.</p>
<p>I've broken this into stages: the sauce, the veggies, and the noodles. For the benefit of shopping lists (and Whisk!) I've provided an awful monolithic pile of ingredients up-front. Yay.</p>
<h2>Ingredients</h2>
<ul>
<li>2 large chicken breasts</li>
<li>2 Tbsp fish sauce</li>
<li>2 tsp ground Cumin seeds</li>
<li>2 tsp ground Coriander seeds</li>
<li>2 tsp Paprika</li>
<li>2 tsp Turmeric</li>
<li>3 tsp Curry powder</li>
<li>3 small chillies</li>
<li>2 onions</li>
<li>5 cloves garlic</li>
<li>1 thumb ginger</li>
<li>2 bay leaves or kaffir lime leaves</li>
<li>2 shoots lemongrass</li>
<li>1 400g can coconut cream</li>
<li>0.5 cup Peanut butter</li>
<li>1 capsicum</li>
<li>1.5c mung bean sprouts (for optional veggie side)</li>
<li>2 spring onions or garlic shoots (for optional veggie side)</li>
<li>1 capsicum, any colour (for optional veggie side)</li>
<li>2 Tbsp dried shrimp (for optional veggie side)</li>
<li>2 Tbsp dried shallots (for optional veggie side)</li>
<li>2 Tbsp peanuts, roughly chopped (for optional veggie side)</li>
<li>Soy sauce</li>
<li>Sesame oil</li>
<li>Egg noodles</li>
<li>Cayenne pepper or other chilli, to taste</li>
<li>Lime juice, to taste</li>
<li>Salt, to taste</li>
<li>Sugar, to taste</li>
<li>MSG, to taste (substitute chicken stock if you want)</li>
<li>Chicken stock, to taste</li>
<li>Vegetable oil</li>
</ul>
<h2>Method</h2>
<ol>
<li>Slice your chicken into reasonably chompy pieces. Maybe 1cm thick, and small enough to fit in your mouth.</li>
<li>Put the chicken in a bowl, pour in the fish sauce. Give it a stir, and leave it to soak.</li>
<li>Dice the onion, and get it in the frypan over medium heat, with only <em>just-enough</em> oil.</li>
<li>While the onion cooks, prepare your spices in a small bowl: cumin, coriander, paprika, turmeric, curry powder.</li>
<li>The onion is still cooking, so chop up your garlic, ginger, and chillies. Give the lemongrass a good thump too.</li>
<li>Get a second frypan onto your hottest element, and get it very hot. Start browning your chicken. Do this in HOT but <em>small</em> batches so it doesn't steam.</li>
<li>Take the onion out of the first fry pan, and add another good tablespoon of oil. </li>
<li>When the oil is hot, tip in your bowl of spices. These are already ground, so they're gonna burn <em>fast</em> - keep them moving, try not to let them smoke.</li>
<li>As soon as the spices are fried off (30~45 seconds), <strong>quickly</strong> throw your onion back in. Give it a stir, then tip in the garlic, ginger, and chilli. Crank the heat up!</li>
<li>Add peanut butter, peanuts, bay leaves, lemongrass, and the juice of half a lime. When the peanut butter is melted, add coconut cream and stir. </li>
<li>Start adding your chicken to the sauce whenever it's ready. After all the chicken is added, reduce heat to a simmer. Try to remember to stir it sometimes.</li>
<li>Time to give it a taste! It'll be bland - this is tuning time. I added a tablespoon of sugar, a teaspoon of MSG, a few grinds of salt, more lime juice, and a teaspoon of dry chicken stock. </li>
<li>Once you've struck the balance of sour/sweet/savoury/salty/spicy that you're looking for, leave it simmer for another 20 minutes or so.</li>
<li>Prep some veggies for a side. I used mung beans, garlic shoots, and a capsicum. Chop these up.</li>
<li>In yEt AnOtHeR pOt, bring a bunch of water to a rolling boil (say 1.5 litres). Get your egg noodles in, and cook according to the packet (often 6mins).</li>
<li>Remember that frypan you fried the chicken in? Get that going again. When hot, throw in your side-veggies, along with some soy sauce and MSG.</li>
<li>Strain the water out of your egg noodles, and start them frying with some oil and soy sauce.</li>
<li>Toss the fried shrimp, fried shallots, and extra peanuts into your nearly-cooked side veggies. Give it a taste, add salt/lime juice/MSG to make it yummy.</li>
<li>QUICK, YOUR NOODLES ARE STICKING TO THE PAN! Turf those out into serving bowls. Spoon the tasty veggies onto half, and your chicken satay onto the other half.</li>
<li>Tell someone else they're on kitchen cleanup duty, and sit down to enjoy!</li>
</ol>
<figure align="center">
<img src="https://www.ericlight.com/images/Food/satay.jpg" width="560" alt="Action shot! My bowl of noodles, showing the fried veggies and satay chicken"/>
<figcaption><em>Delicious.</em></figcaption>
</figure>Configuring a custom SSL certificate in Zentyal2021-04-25T00:00:00+12:002021-04-25T22:04:22+12:00Eric Lighttag:www.ericlight.com,2021-04-25:/configuring-a-custom-ssl-certificate-in-zentyal.html<p>Zuper-quick post for when this bites me again in the future!</p>
<p>Tonight I upgraded from Zentyal 6.2 to Zentyal 7.0. Smooth as butter, everything went great.</p>
<p>Until I logged in, and my shiny Actual Paid Money SSL certificate had vanished, replaced by a self-signed commoner's certificate. Piffle.</p>
<p>Instructions for installing a custom SSL certificate in Zentyal are actually kinda shaky, so here you go:</p>
<div class="highlight"><pre><span></span><code><span class="nb">cd</span> /var/lib/zentyal/conf/ssl/
mkdir old
mv * old
nano ssl.key
nano ssl.cert
cat ssl.cert ssl.key > ssl.pem
chmod …</code></pre></div><p>Zuper-quick post for when this bites me again in the future!</p>
<p>Tonight I upgraded from Zentyal 6.2 to Zentyal 7.0. Smooth as butter, everything went great.</p>
<p>Until I logged in, and my shiny Actual Paid Money SSL certificate had vanished, replaced by a self-signed commoner's certificate. Piffle.</p>
<p>Instructions for installing a custom SSL certificate in Zentyal are actually kinda shaky, so here you go:</p>
<div class="highlight"><pre><span></span><code><span class="nb">cd</span> /var/lib/zentyal/conf/ssl/
mkdir old
mv * old
nano ssl.key
nano ssl.cert
cat ssl.cert ssl.key > ssl.pem
chmod <span class="m">0400</span> ssl*
</code></pre></div>
<p>That's it! Your Private Key lives in <code>ssl.key</code>, and your SSL certificate lives in <code>ssl.cert</code>. </p>
<p>Reboot, and job done.</p>Blocking bad extensions and extortion with iRedMail2021-04-12T00:00:00+12:002021-04-12T22:11:44+12:00Eric Lighttag:www.ericlight.com,2021-04-12:/blocking-bad-extensions-and-extortion-with-iredmail.html<p>Turns out this is my third Amavis article. I guess it's just one of those systems.</p>
<p><em>Heads up, if you're trying to do this, make sure you also read <a href="https://www.ericlight.com/respecting-amavis-banned-extensions-setting.html">my other article</a> about the "banned_files_lover" thing.</em></p>
<p>Today I'm on a mission to:
1. Drop all incoming Office '97 files (they're predominantly malicious these days)
1. Drop all incoming Macro-enabled Office 2007+ files (there aren't legitimate reasons to receive these <em>in my scenario</em>)
1. Drop any emails containing a .onion address
1. Drop any emails containing a bitcoin wallet</p>
<h2>Dropping Attachments …</h2><p>Turns out this is my third Amavis article. I guess it's just one of those systems.</p>
<p><em>Heads up, if you're trying to do this, make sure you also read <a href="https://www.ericlight.com/respecting-amavis-banned-extensions-setting.html">my other article</a> about the "banned_files_lover" thing.</em></p>
<p>Today I'm on a mission to:
1. Drop all incoming Office '97 files (they're predominantly malicious these days)
1. Drop all incoming Macro-enabled Office 2007+ files (there aren't legitimate reasons to receive these <em>in my scenario</em>)
1. Drop any emails containing a .onion address
1. Drop any emails containing a bitcoin wallet</p>
<h2>Dropping Attachments</h2>
<p>The attachment block is easily handled by Amavis. In iRedMail on Debian, the configuration file is found at <code>/etc/amavis/conf.d/50-user</code>. Open your config file, and scroll down to the section where the <code>$banned_filename_re</code> variable is set. Insert the following line:</p>
<div class="highlight"><pre><span></span><code> qr'.\.(doc|dot|docm|docb|xls|xlm|xlt|xlsm|xlsb|
xla|xlam|ppt|pps|pptm|potm|ppam|ppsm|sldm)$'i, # Office '97-2003 and Macro-enabled files
qr'.\.(adn|accdb|accdr|accdt|accda|mdw|accde|mam|maq|mar|mat|
maf|laccdb|ade|adp|mdb|cdb|mda|mdn|mdt|mdf|mde|ldb)$'i, # Microsoft Access files
qr'^\.pub$', # Microsoft Publisher files
</code></pre></div>
<p>That will block all core Office '97-2003 files, as well as all Macro-enabled Office 2007-365 files.</p>
<p>By default, this will <strong>silently</strong> reject mails containing these attachments. If you want senders to receive a bounce message, search for the <code>$final_banned_destiny</code> variable and make sure it's set to <code>D_BOUNCE</code>.</p>
<h2>Dropping .onion and BTC</h2>
<p>This part happens in Postfix, and it's more-super-easy than the last bit. To configure Postfix's body checks, edit <code>/etc/postfix/body_checks.pcre</code>. I simply added the following:</p>
<div class="highlight"><pre><span></span><code>/(\w+\.onion)/ REJECT This mail server does not accept references to .onion addresses (${1})
/(\b(bc1|[13])[a-zA-HJ-NP-Z0-9]{25,39})/ DISCARD Bitcoin wallet detected (${1})
</code></pre></div>
<p>I used the REJECT directive for testing, but to be honest I don't want to send bounces back to these people, so I changed to DISCARD after it was working. You can see the difference above.</p>
<p>The text after the REJECT directive is returned to the sender, and the text after the DISCARD directive is logged. The variable <code>${1}</code> contains the detected string, and is appended to the response message.</p>
<p>That's the end! Safety. Yes.</p>
<h1>Acknowledgements</h1>
<p>Thanks to Brad and Hamish for this post - Brad for the regex, Hamish for the idea, and both of them for the review!</p>Using Caddy to enable MTA-STS2021-01-19T00:00:00+13:002021-01-20T20:35:36+13:00Eric Lighttag:www.ericlight.com,2021-01-19:/using-caddy-to-enable-mta-sts.html<p>About 7 months ago, I left Nginx and <a href="https://www.ericlight.com/moving-to-the-caddy-web-server.html">moved to Caddy</a>. I've found it super easy, and have now experienced using it as a reverse proxy, a static site server (this one!), as well as a hosting a <a href="https://shrug.ericlight.com">handy place</a> for me to copy my favourite <a href="http://kaomoji.ru">Kaomoji</a>.</p>
<p><em><strong>Update 2021-01-20</strong></em>: I had a bug! By default, Caddy serves this without a Content-Type header. However, the <a href="https://tools.ietf.org/html/rfc8461#section-3.2">RFC</a> specifies that the response should be explicitly <code>Content-Type "text/plain"</code>. Thanks to <a href="https://github.com/klausenbusk/">klausenbusk</a> for letting me know!</p>
<p><em>Note: the Caddyfile fragment to generate <a href="https://shrug.ericlight.com">https://shrug …</a></em></p><p>About 7 months ago, I left Nginx and <a href="https://www.ericlight.com/moving-to-the-caddy-web-server.html">moved to Caddy</a>. I've found it super easy, and have now experienced using it as a reverse proxy, a static site server (this one!), as well as a hosting a <a href="https://shrug.ericlight.com">handy place</a> for me to copy my favourite <a href="http://kaomoji.ru">Kaomoji</a>.</p>
<p><em><strong>Update 2021-01-20</strong></em>: I had a bug! By default, Caddy serves this without a Content-Type header. However, the <a href="https://tools.ietf.org/html/rfc8461#section-3.2">RFC</a> specifies that the response should be explicitly <code>Content-Type "text/plain"</code>. Thanks to <a href="https://github.com/klausenbusk/">klausenbusk</a> for letting me know!</p>
<p><em>Note: the Caddyfile fragment to generate <a href="https://shrug.ericlight.com">https://shrug.ericlight.com</a> looks like this:</em></p>
<div class="highlight"><pre><span></span><code>shrug.ericlight.com { respond "<meta charset='UTF-8'>¯\_(ツ)_/¯" }
</code></pre></div>
<p>Anyway, once I'd used Caddy's <code>respond</code> directive, it was a simple step to take it forward and use it to serve my handy-dandy MTA-STS policy file!</p>
<p>Simply add this new Server block to your Caddyfile:</p>
<div class="highlight"><pre><span></span><code>mta-sts.ericlight.com {
respond "version: STSv1
mode: testing
mx: in1-smtp.messagingengine.com
mx: in2-smtp.messagingengine.com
max_age: 86401"
header Content-Type "text/plain; charset=utf-8"
}
</code></pre></div>
<p>This simple Server block will get you a shiny HTTPS certificate, redirect any HTTP visitors to HTTPS, and will provide enquirers with your MTA policy file. <em>(Obviously, replace my domain name and MX entries with your own.)</em></p>
<p>Sharp observers will notice that the MTA-STS policy file should be hosted at <code>https://mta-sts.ericlight.com/.well-known/mta-sts.txt</code>... but that's the elegance of the Respond directive in Caddy: <em>wherever</em> you go at <code>mta-sts.ericlight.com</code>, you get exactly that response!</p>
<p>Example: <a href="https://mta-sts.ericlight.com/my/hovercraft/is/full/of/eels.txt">https://mta-sts.ericlight.com/my/hovercraft/is/full/of/eels.txt</a></p>
<p>Okay, that was easy... the next part is just creating your <em><strong>three</strong></em> DNS records:</p>
<ul>
<li>
<p><strong>Record #1:</strong> An A record for <code>mta-sts.ericlight.com</code>, pointing to your Caddy server.</p>
</li>
<li>
<p><strong>Record #2:</strong> A TXT record at <code>_mta-sts.ericlight.com</code>, reading <code>v=STSv1; id=20210112</code>. (Note the underscore! Also, the ID can be anything.)</p>
</li>
<li>
<p><strong>Record #3:</strong> A TXT record at <code>_smtp._tls.ericlight.com</code>, reading <code>v=TLSRPTv1; rua=mailto:tls-reports@targetdomain.com</code>. (update that email address)</p>
</li>
</ul>
<p>... There you go! Now you have a shiny new MTA-STS policy, and your Reporting email target (configured in DNS Record #3) will start reciving daily reports from sending mail servers, letting you know if your policy is working correctly.</p>
<p>Eventually (once you're sure it's all configured properly), you should change your <code>testing</code> policy to <code>enforce</code>. When you do this, <strong>make sure you update the ID in your TXT Record!</strong> This is how sending mail servers know that there has been a policy update.</p>
<p>Enjoy!</p>Getting TrueNAS (FreeNAS 12) to work with an APC NMC2 UPS (AP9631)2021-01-14T00:00:00+13:002021-01-15T00:18:43+13:00Eric Lighttag:www.ericlight.com,2021-01-14:/getting-truenas-freenas-12-to-work-with-an-apc-nmc2-ups-ap9631.html<p>TrueNAS, and FreeNAS before it, has supported UPS via the NUT software package since forever. But most people using it seem to be using USB-connected UPS devices. I don't have one of these. I'm dealing with an IPv4-based APC ups, specifically the Smart-UPS X 1500 (SMX1500RMI2UNC), with an AP9631 NMC2 card.</p>
<p>You're probably here because you're in the same boat: trying to set up a non-USB or Ethernet-based UPS under FreeNAS/TrueNAS, and you can't. You've noticed the TrueNAS console <em>will not shut up</em> about errors which read something like …</p><p>TrueNAS, and FreeNAS before it, has supported UPS via the NUT software package since forever. But most people using it seem to be using USB-connected UPS devices. I don't have one of these. I'm dealing with an IPv4-based APC ups, specifically the Smart-UPS X 1500 (SMX1500RMI2UNC), with an AP9631 NMC2 card.</p>
<p>You're probably here because you're in the same boat: trying to set up a non-USB or Ethernet-based UPS under FreeNAS/TrueNAS, and you can't. You've noticed the TrueNAS console <em>will not shut up</em> about errors which read something like: </p>
<p><code>nut plugin: nut_connect: upscli_connect (localhost, 3493) failed: Connection failure: Connection refused</code>. (Or perhaps port 161)</p>
<p><em>"But why?"</em>, you say. <em>"I've given TrueNAS my UPS hostname, why is it always trying to talk to localhost? And what is this port 3493, when SNMP is 161?"</em></p>
<p>What's happening is that <code>upscli</code> is trying to talk to the <code>upsd</code> damon <em>on your TrueNAS server</em>, which is expected to listen on port 3493 - it's <strong>upsd</strong> which then does the talky with the SNMP driver, which in turn does the talky with the UPS. This is why the TrueNAS console logs look like it's just shouting at itself.</p>
<p>Okay, let's get into it:</p>
<h2>UPS Configuration</h2>
<p>First, you need to enable SNMP on your AP9631. This was pretty straightforward, but remember that you need to go:</p>
<ol>
<li>Configuration -> Network -> SNMPv1 -> Access -> <strong>Enable</strong></li>
<li>Configuration -> Netowrk -> SNMPv1 -> Access Control, and make sure the <code>public</code> community is set to be accessible from 0.0.0.0</li>
<li>Reboot your NMC2 card.</li>
</ol>
<p>This configuration should work with the defaults that the NUT SNMP driver expects - I suggest you get it working like this for now, then tweak to SNMPv3 once you have a confirmed-working connection.</p>
<h2>TrueNAS Configuration</h2>
<p>Your UPS configuration menu is under TrueNAS -> Services -> UPS. Configure your TrueNAS UPS section like so:</p>
<h3>General Options section:</h3>
<ul>
<li><strong>Identifier:</strong> Up to you, but do yourself a favour and make it <code>ups</code>.</li>
<li><strong>UPS Mode:</strong> Master</li>
<li><strong>Driver:</strong> "Various ups 3 (various) SNMP - RFC 1628 (snmp-ups, experimental)" -- once you save, this will simply display as <code>snmp-ups$(various)</code></li>
<li><strong>Port or Hostname:</strong> The hostname of the ups, hopefully something simple like <code>ups.mydomain.local</code></li>
</ul>
<h3>Monitor section:</h3>
<p>Leave the Monitor User, Monitor Password, Extra users, and Remote Monitor all blank/default for now - you can change them once the UPS is talking to you. Note I don't believe it's important to change the Monitor Password under this configuration, as <code>upsd</code> only listens on the loopback address.</p>
<h3>Shutdown and Email sections</h3>
<p>I shall leave in your capable hands.</p>
<h3>Other Options:</h3>
<ul>
<li><strong>Auxiliary Parameters (ups.conf):</strong> This is where you override the SNMP defaults, if desired. By default, NUT will use SNMPv1 and the 'public' community. <a href="https://networkupstools.org/docs/man/snmp-ups.htm">See here for all config options</a> availble for the SNMP driver. You could do something like this, if you want:</li>
</ul>
<div class="highlight"><pre><span></span><code><span class="na">community</span><span class="o">=</span><span class="s">yaysecurity</span>
<span class="na">snmp_version</span><span class="o">=</span><span class="s">3</span>
<span class="na">privProtocol</span><span class="o">=</span><span class="s">AES</span>
</code></pre></div>
<ul>
<li><strong>Auxiliary Parameters (upsd.conf):</strong> <code>LISTEN 127.0.0.1 3493</code></li>
</ul>
<p>That last line was the magic - this is the bit that makes upsd <em>not only</em> listen on port 161 (whyyyy), but <em>also</em> listen on 3493, which is where the rest of the UPS subsystem expects to find UPS data!</p>
<h1>Other interesting tidbits:</h1>
<ul>
<li>Running <code>upsc -l</code> should list all UPS instances configured on your server. Since I've got one, called 'ups', I see:</li>
</ul>
<div class="highlight"><pre><span></span><code># upsc -l
ups
</code></pre></div>
<ul>
<li>If <code>upsc -l</code> gives you a Connection Refused error, check <code>/usr/local/etc/nut/upsd.conf</code> to make sure it's listening on 3493. If not, add your auxiliary parameter in TrueNAS and restart the service.</li>
</ul>
<div class="highlight"><pre><span></span><code># upsc ups
Error: Connection failure: Connection refused
# cat /usr/local/etc/nut/upsd.conf
LISTEN 127.0.0.1 161
LISTEN ::1 161
# sockstat -4 -l | grep upsd
uucp upsd 99934 6 tcp4 127.0.0.1:161 *:*
</code></pre></div>
<p><em>Above: upsd is definitely not listening on the expected port</em></p>
<ul>
<li>
<p><strong>NUT Config files</strong>: These live under <code>/usr/local/etc/nut/</code>. The folder is deleted and recreated every time you edit something in the TrueNAS GUI, so if you're in that folder and change something in the GUI, you'll need to do the whole <code>cd /usr/local/etc/nut</code> again. No you can't do <code>cd ../nut</code>, because the whole inode is gone, so the OS doesn't know where you are anymore.</p>
</li>
<li>
<p><strong>Testing your UPS</strong>: Once <code>upsd</code> is listening on 3493, you should be able to run <code>upsc ups</code>, and it will query your UPS for data. Note that "ups" is your UPS identifier from the "General Options" section, also found as the first line of <code>/usr/local/etc/nut/ups.conf</code>:</p>
</li>
</ul>
<div class="highlight"><pre><span></span><code># cat /usr/local/etc/nut/ups.conf
[ups]
driver = snmp-ups
port = ups.mydomain.local
desc =
pollfreq = 15
# upsc ups
ambient.humidity: 0.00
ambient.temperature: 23.0
battery.charge: 100.00
battery.date: 05/15/2017
battery.packs: 0.00
battery.runtime: 1221.00
battery.runtime.low: 600
battery.voltage: 54.50
device.mfr: APC
device.model: Smart-UPS X 1500
[...]
</code></pre></div>
<p>I think that pretty much covers it. I hope this has been helpful to someone - at very least, I hope it's helpful to future-me!</p>
<p>It's been a little while since I've worked with UPS management software. I like to think it's because my day job isn't in infrastructure anymore, but also to be honest the whole UPS scene is fairly ugly. I recall speaking with an electrical engineer from Schneider a while ago, who jokingly said something like "creating a new UPS or CNC communications protocol is almost a rite of passage for any new engineer". I can see why... when you're new, and see something <em>superbly awful</em>, it's quite compelling to try and fix it! But decades now of dependencies really do add up to be a burden.</p>The Actual Best Sous Vide Eggs... ™2020-12-28T00:00:00+13:002020-12-28T14:58:21+13:00Eric Lighttag:www.ericlight.com,2020-12-28:/the-actual-best-sous-vide-eggs-tm.html<p>Inkbird were having a special in November, so I got a sous vide for Christmas! There are heaps of places with recipes for the best sous vide eggs, most notably the always-outstanding <a href="https://www.seriouseats.com/2013/10/sous-vide-101-all-about-eggs.html">Serious Eats</a>, but also an excellent write-up on <a href="https://saltpepperskillet.com/recipes/sous-vide-poached-eggs/">Salt Pepper Skillet</a>, and of course sous vide manufacturer <a href="https://anovaculinary.com/quick-guide-to-cooking-sous-vide-eggs-with-anova/">Anova Culinary</a> with a somewhat briefer post.</p>
<p>I submit to you that <em>none of these</em> are the best sous vide eggs. In my eyes, the best egg has a completely opaque white (not rubbery and not snot), with a semicooked gooey …</p><p>Inkbird were having a special in November, so I got a sous vide for Christmas! There are heaps of places with recipes for the best sous vide eggs, most notably the always-outstanding <a href="https://www.seriouseats.com/2013/10/sous-vide-101-all-about-eggs.html">Serious Eats</a>, but also an excellent write-up on <a href="https://saltpepperskillet.com/recipes/sous-vide-poached-eggs/">Salt Pepper Skillet</a>, and of course sous vide manufacturer <a href="https://anovaculinary.com/quick-guide-to-cooking-sous-vide-eggs-with-anova/">Anova Culinary</a> with a somewhat briefer post.</p>
<p>I submit to you that <em>none of these</em> are the best sous vide eggs. In my eyes, the best egg has a completely opaque white (not rubbery and not snot), with a semicooked gooey yolk like a cross between honey and custard. Like this one:</p>
<figure align="center">
<img src="https://www.ericlight.com/images/Food/egg.jpg" width="400" alt="My beautiful egg, smooshed on a piece of bread."/>
<figcaption><em>Yum.</em></figcaption>
</figure>
<p>The closest recipe on the pages I cited is the 13.5 minute egg at 75°C. This is really close, but I found the yolk was a bit overcooked, and the white undercooked. Absolute conundrum.</p>
<p>My fix? A slightly hotter temperature, and take your eggs straight outta the fridge. I found 76°C (169°F) for the vaunted 13.5 minutes managed to get the outer white to a non-snot texture, while the pre-chilledness of the egg kept the yolk from overcooking.</p>Logging DNS queries, for both pfSense and Zentyal server2020-12-06T00:00:00+13:002020-12-06T22:33:09+13:00Eric Lighttag:www.ericlight.com,2020-12-06:/logging-dns-queries-for-both-pfsense-and-zentyal-server.html<p>Logs of your client DNS queries can be a really good tool for incident response. I've finally got this implemented but it was much more of a struggle than I expected it to be, so here's my story!</p>
<p>We've got a pfSense firewall running as a DNS fowarder, and a <a href="https://www.zentyal.com">Zentyal</a> server running BIND9 as the authoritative local server. The firewall rules block all UDP/53, so all DNS queries go either directly to the firewall, or (more commonly) to the Zentyal server for resolution. This means we have two …</p><p>Logs of your client DNS queries can be a really good tool for incident response. I've finally got this implemented but it was much more of a struggle than I expected it to be, so here's my story!</p>
<p>We've got a pfSense firewall running as a DNS fowarder, and a <a href="https://www.zentyal.com">Zentyal</a> server running BIND9 as the authoritative local server. The firewall rules block all UDP/53, so all DNS queries go either directly to the firewall, or (more commonly) to the Zentyal server for resolution. This means we have two places that resolve DNS queries which we want to forward off to our syslog server.</p>
<h2>pfSense</h2>
<p>Unbound is a <em>super</em> simple DNS forwarder, and the configuration is wonderfully straightforward. It did take me quite a while to figure it out, but in the end it was a simple oversight on my part.</p>
<p>To get pfSense/Unbound to forward DNS queries to your syslog server, simply open the Services -> DNS Resolver page, click 'Display Custom options', and add these two lines:</p>
<div class="highlight"><pre><span></span><code><span class="na">server:</span>
<span class="na">log-queries: yes</span>
</code></pre></div>
<p>I spent hours fiddling before I realised I was missing the empty "server:" directive. -__-</p>
<p>This will log all DNS queries that Unbound deals with. These logs go to the standard internal pfSense log; if you want them to be replicated off to an external syslog server, go Status -> System Logs -> Settings. Scroll down to the "Remote Log Servers" section and add your syslog server there. (I'm not covering syslog listener config in this particualar post!)</p>
<h2>Zentyal</h2>
<p>Yeah this one was harder to figure out. Because Zentyal overwrites the config at <em>every damn opportunity</em>, you can't just edit <code>/etc/bind/named.conf.options</code>, like what you find in <a href="https://www.thegeekdiary.com/how-to-enable-bind-query-logging-to-find-out-whos-querying-a-name-server/">most articles</a>... it may work for a moment, but it'll be overwritten.</p>
<p>The real answer to editing Zentyal's config files is outlined at <a href="https://doc.zentyal.org/en/appendix-c.html#stubs">https://doc.zentyal.org/en/appendix-c.html#stubs</a>:</p>
<div class="highlight"><pre><span></span><code>cp /usr/share/zentyal/stubs/dns/named.conf.options.mas /etc/zentyal/stubs/dns/named.conf.options.mas
</code></pre></div>
<p>Once you've copied the stub into a place where it won't be clobbered, edit it and zoom right down to the bottom line, which looks like:</p>
<div class="highlight"><pre><span></span><code><span class="na">logging { category lame-servers { null; }; };</span>
</code></pre></div>
<p>This is the line you need to replace. Now, you can go as ham as you want here. I've actually used the sample provided by ISC themselves, which you can find at <a href="https://kb.isc.org/docs/aa-01526">https://kb.isc.org/docs/aa-01526</a>. However, that's really robust and possibly more than you may need. A bare minimum would probably look like:</p>
<div class="highlight"><pre><span></span><code><span class="na">logging { </span>
<span class="na">channel queries_log {</span>
<span class="na">syslog named;</span>
<span class="na">print-time yes;</span>
<span class="na">print-category yes;</span>
<span class="na">print-severity yes;</span>
<span class="na">severity info;</span>
<span class="na">};</span>
<span class="na">};</span>
</code></pre></div>
<p>Note - when I tried to use the ISC sample wholesale, I needed to change a couple small things:</p>
<ol>
<li>Changed all <code>/var/named/log</code> output destinations to <code>/var/log/named</code></li>
<li>The lines for <code>category zoneload</code> and <code>category trust-anchor-telemetry</code> need to be removed for Zentyal 6.2's version of BIND9 </li>
<li>I needed to create <code>/var/log/named</code>, and make sure it was writeable by the bind user</li>
</ol>
<p>I think that covers it, I hope this helps someone! I've actually even taken the time today to create a <a href="https://github.com/zentyal/zentyal/pull/2005">Pull Request</a> in the Zentyal GitHub, we'll see if it ends up getting merged!</p>Daaaaaal!2020-11-24T00:00:00+13:002020-11-24T21:42:40+13:00Eric Lighttag:www.ericlight.com,2020-11-24:/daaaaaal.html<p>I've loved daal (or dal or dahl or dhal etc) since my trip to India in 2019... Ugh, that seems so interminably long ago now, in the final weeks of the long decade of 2020. Anyway.</p>
<figure align="center">
<img src="https://www.ericlight.com/images/Food/daal-india.jpg" width="400" alt="A dark, brown-green daal makhani, with swirls of cream visible."/>
<figcaption><em>Daal makhani in Varanasi.</em></figcaption>
</figure>
<p>So there's this recipe I've followed a handful of times. I like it, it's similar to what I enjoyed while travelling through Jaipur, but it doesn't really <em>kick</em> the same way that the food in India did, so I always find myself tweaking it. The base recipe came from <a href="https://thewanderlustkitchen.com/indian-red-lentil-dal/">https …</a></p><p>I've loved daal (or dal or dahl or dhal etc) since my trip to India in 2019... Ugh, that seems so interminably long ago now, in the final weeks of the long decade of 2020. Anyway.</p>
<figure align="center">
<img src="https://www.ericlight.com/images/Food/daal-india.jpg" width="400" alt="A dark, brown-green daal makhani, with swirls of cream visible."/>
<figcaption><em>Daal makhani in Varanasi.</em></figcaption>
</figure>
<p>So there's this recipe I've followed a handful of times. I like it, it's similar to what I enjoyed while travelling through Jaipur, but it doesn't really <em>kick</em> the same way that the food in India did, so I always find myself tweaking it. The base recipe came from <a href="https://thewanderlustkitchen.com/indian-red-lentil-dal/">https://thewanderlustkitchen.com/indian-red-lentil-dal/</a> ... and then I looked up a specifically Rajasthani daal recipe and found <a href="https://www.archanaskitchen.com/rajasthani-dal-recipe">this one</a> which is super similar. The place I've settled is in the middle of the two.</p>
<h1>Ingredients and Method, jumbled into one</h1>
<h3>Step One (the pot)</h3>
<ul>
<li>3/4 cup Red Lentils - rinsed</li>
<li>1/4 cup Green Lentils - rinsed</li>
<li>3 cups water (not boiling, just room temp)</li>
</ul>
<p>After rinsing, put the lentils and water in a medium pot over medium heat. Let them simmer while you prep the rest.</p>
<h3>Step Two (the fry pan)</h3>
<ul>
<li>1.5 tsp Cumin seeds</li>
<li>1 Cinnamon stick</li>
<li>1 Tbsp butter or ghee</li>
<li>1 Tbsp oil</li>
</ul>
<p>Put these into a medium fry pan; don't turn it on yet.</p>
<h3>Step Three (the base spices)</h3>
<ul>
<li>6 cloves of garlic, chopped</li>
<li>1.5 Tbsp of ginger, I just used the crushed stuff</li>
<li>1 large onion, diced. Use different types of onion if you're feeling ✧・゚: <em>✧・゚:</em> <em>faaancy</em> <em>:・゚✧</em>:・゚✧</li>
<li>2 green chilies. Dump the seeds and chop them up.</li>
<li>If you don't have chilies, drop in 2 Tbsp of Salsa Picante instead, for that capsicum-type flavour.</li>
</ul>
<p>Prep the above, and put them all into a small bowl.</p>
<h3>Step Four (get your heat on)</h3>
<p>At this point, turn the frypan on to medium heat. Let the cumin and cinnamon sizzle in the oil for about a minute, until the scent starts to pop.</p>
<p>Just before it starts to smoke, throw in the contents of your small bowl from Step Three, give it a stir, and crank the heat up to eleven.</p>
<h3>Step Five (getting serious now)</h3>
<ul>
<li>1 tsp turmeric</li>
<li>1 tsp paprika</li>
<li>2/3 tsp cardamom (either ground, or smash the seeds in a pestle)</li>
<li>1/2 tsp red chilli powder</li>
<li>2 bay leaves</li>
<li>1 tomato, diced</li>
<li>Spinach! I used about a cup worth of the frozen chopped stuff (defrosted first, of course)</li>
</ul>
<p>Give your frypan a stir every couple of minutes. By the time you've finished chopping the tomato and getting the rest of this together, the onions should be transparent and the whole thing should be smelling amazing.</p>
<p>Add all these ingredients to the frypan and give it another stir. Stir up the lentils as well, they should have been simmering for a few minutes by now!</p>
<h3>Step Six (tune those flavours)</h3>
<p>This last part really comes down to personal tastes, but here's my go:</p>
<ul>
<li>1/2 tsp salt</li>
<li>1/2 tsp Aromat or MSG</li>
<li>1 tsp Vegeta vegetable stock</li>
<li>1 tsp dried coriander</li>
<li>The juice of one lemon</li>
<li>1 cup of coconut cream, regular cream, or yoghurt</li>
</ul>
<p>Once the lentils have thickened up, mix in all the above, and then stir in the now-cooked contents of your frypan. That's it, your daal is assembled! Taste and tweak as desired, and then serve on rice.</p>
<figure align="center">
<img src="https://www.ericlight.com/images/Food/daal-home.jpg" width="400" alt="My daal, in the pot at home. Much more yellow cast than the makhani style above."/>
<figcaption><em>The end result.</em></figcaption>
</figure>
<p><em>Enjoy!</em></p>iRedMail, SpamAssassin, and Lynis2020-11-02T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2020-11-02:/iredmail-spamassassin-and-lynis.html<p>I really like iRedMail, and I also really like Lynis.</p>
<p>However, they don't exactly like <em>each other</em>... or, more accurately, some of Lynis' recommendations can cause a couple iRedMail components to fail. Today we're talking about SpamAsassin.</p>
<p>One of the suggestions from Lynis is to turn off the 'execute' bit on compilers for users who aren't either the owner or in the owner group (the 'other' execute bit). For example:</p>
<div class="highlight"><pre><span></span><code>root@server:/# chmod o-x /usr/bin/as
root@server:/# chmod o-x /usr/bin/gcc
</code></pre></div>
<p>Easy peasy! But once you do …</p><p>I really like iRedMail, and I also really like Lynis.</p>
<p>However, they don't exactly like <em>each other</em>... or, more accurately, some of Lynis' recommendations can cause a couple iRedMail components to fail. Today we're talking about SpamAsassin.</p>
<p>One of the suggestions from Lynis is to turn off the 'execute' bit on compilers for users who aren't either the owner or in the owner group (the 'other' execute bit). For example:</p>
<div class="highlight"><pre><span></span><code>root@server:/# chmod o-x /usr/bin/as
root@server:/# chmod o-x /usr/bin/gcc
</code></pre></div>
<p>Easy peasy! But once you do this, you might start getting the following in your daily iRedMail Cron reports:</p>
<div class="highlight"><pre><span></span><code>/etc/cron.daily/spamassassin:
/bin/sh: 1: x86_64-linux-gnu-gcc: Permission denied
make: *** [Makefile:346: body_0.o] Error 126
command 'make PREFIX=/tmp/.spamassassin23046Zmmrr9tmp/ignored INSTALLSITEARCH=/var/lib/spamassassin/compiled/5.028/3.004002 >>/tmp/.spamassassin23046Zmmrr9tmp/log' failed: exit 2
</code></pre></div>
<p>There are probably a bunch of ways to fix this. My way, I'm sure, is not the best way... however it was quick and easy, and it worked.</p>
<div class="highlight"><pre><span></span><code>root@server:/# chgrp debian-spamd /usr/bin/as
root@server:/# chgrp debian-spamd /usr/bin/gcc
root@server:/# runuser -l debian-spamd -c sa-compile
</code></pre></div>
<p>Look ma, no more errors!</p>
<p>This solution really <em>only</em> works for me because debian-spamd is the only non-root user that calls these compilers. If I had another user which needed to call them, I'd have to come up with a better fix. But for a standalone iRedMail server, this does the trick!</p>iRedMail: Daily user unknown entries from backup_sogo.sh2020-11-01T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2020-11-01:/iredmail-daily-user-unknown-entries-from-backup_sogosh.html<p>If you've been running iRedMail for a while, eventually you'll probably start seeing 'user unknown' events in your daily logs:</p>
<div class="highlight"><pre><span></span><code>* Backup all users' data under /var/vmail/backup/sogo/2020/11/01
<0x0x5574a64c36b0[SOGoCache]> Cache cleanup interval set every 300.000000 seconds
<0x0x5574a64c36b0[SOGoCache]> Using host(s) '127.0.0.1' as server(s)
2020-11-01 09:29:12.784 sogo-tool[29749:29749] user 'abdulm' unknown
2020-11-01 09:29:12.786 sogo-tool[29749:29749] user 'bent' unknown
2020-11-01 09:29:12.786 sogo-tool[29749:29749] user 'brettr' unknown
2020-11-01 09:29 …</code></pre></div><p>If you've been running iRedMail for a while, eventually you'll probably start seeing 'user unknown' events in your daily logs:</p>
<div class="highlight"><pre><span></span><code>* Backup all users' data under /var/vmail/backup/sogo/2020/11/01
<0x0x5574a64c36b0[SOGoCache]> Cache cleanup interval set every 300.000000 seconds
<0x0x5574a64c36b0[SOGoCache]> Using host(s) '127.0.0.1' as server(s)
2020-11-01 09:29:12.784 sogo-tool[29749:29749] user 'abdulm' unknown
2020-11-01 09:29:12.786 sogo-tool[29749:29749] user 'bent' unknown
2020-11-01 09:29:12.786 sogo-tool[29749:29749] user 'brettr' unknown
2020-11-01 09:29:12.786 sogo-tool[29749:29749] user 'catalinar' unknown
2020-11-01 09:29:12.787 sogo-tool[29749:29749] user 'clinth' unknown
2020-11-01 09:29:12.787 sogo-tool[29749:29749] user 'danield' unknown
2020-11-01 09:29:12.787 sogo-tool[29749:29749] user 'dannyn' unknown
2020-11-01 09:29:12.788 sogo-tool[29749:29749] user 'darcyk' unknown
2020-11-01 09:29:12.788 sogo-tool[29749:29749] user 'davidl' unknown
* Compress backup files.
</code></pre></div>
<p>This is because removal of an iRedMail user doesn't remove the corresponding SOGo user data. You can take care of this with <code>sogo-tool</code>:</p>
<div class="highlight"><pre><span></span><code>root@server:/# sogo-tool remove abdulm@<domain.xyz> bent@<domain.xyz> brettr@<domain.xyz>
</code></pre></div>
<p>... etc. Once you're done, run the backup again to make sure you've got them all:</p>
<div class="highlight"><pre><span></span><code>root@server:/# /bin/bash /var/vmail/backup/backup_sogo.sh
* Backup all users data under /var/vmail/backup/sogo/2020/11/01
<0x0x563fd0e2b6b0<span class="o">[</span>SOGoCache<span class="o">]</span>> Cache cleanup interval <span class="nb">set</span> every <span class="m">300</span>.000000 seconds
<0x0x563fd0e2b6b0<span class="o">[</span>SOGoCache<span class="o">]</span>> Using host<span class="o">(</span>s<span class="o">)</span> <span class="s1">'127.0.0.1'</span> as server<span class="o">(</span>s<span class="o">)</span>
* Compress backup files.
</code></pre></div>Your mate Eric, and his journey through depression2020-10-08T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2020-10-08:/your-mate-eric-and-his-journey-through-depression.html<p>A couple of months ago, the team at my day job asked me to write something for <a href="https://www.mhaw.nz/">Mental Health Awareness Week</a>, so today I'm sharing some of my personal experiences around depression. It's one of my longer articles, but the key message I want you to hear is: If you're struggling, speak with someone. Seriously, just lean over to your mate now and say "Hey, did you see that article from Eric today?" – that's all it takes to start a conversation, and believe me: sharing your feelings is a solid …</p><p>A couple of months ago, the team at my day job asked me to write something for <a href="https://www.mhaw.nz/">Mental Health Awareness Week</a>, so today I'm sharing some of my personal experiences around depression. It's one of my longer articles, but the key message I want you to hear is: If you're struggling, speak with someone. Seriously, just lean over to your mate now and say "Hey, did you see that article from Eric today?" – that's all it takes to start a conversation, and believe me: sharing your feelings is a solid way to start getting on top of them.</p>
<figure>
<img class='img-center' style="width:75%" src="https://www.ericlight.com/images/Ramblings/mhaw.jpg" alt="Mental Health Awareness Week banner"/>
</figure>
<p>The year was 2011, maybe February, about 10pm... the kids were in bed, school lunches packed, teeth brushed. It was a normal part of a normal bedtime routine for the whole household. I don't particularly recall anything <em>happening</em>... but I remember looking at my wife and saying, "<em>Shit... I think I'm depressed</em>". In the morning I phoned my doc (that was the hardest part) who started me on <a href="https://www.healthnavigator.org.nz/medicines/s/ssri-antidepressants/">Fluoxetine</a> - the medication that supported me throughout my recovery. Making that phone call the first step in a long journey, but it cemented my realisation that I was struggling, and that I needed help.</p>
<p>The <a href="https://www.mentalhealth.org.nz/">New Zealand Mental Health Foundation</a> says that one in six New Zealand adults have been <em>diagnosed</em> with a common mental disorder (depression, anxiety, bipolar) at some time in their lives. And behind every diagnosis, there are a host of other staunch people who have struggled and pushed to battle through it silently, sometimes with heart-breaking results. (Rest easy, Deano 💔). According to the World Health Organization (<a href="https://www.health.govt.nz/our-work/mental-health-and-addictions/mental-health">via health.govt.nz</a>), mental illness accounts for 15% of the total burden of disease in the developed world, with depression set to become the second leading cause of disability in the world by *<em>checks watch</em>* ... 2020.</p>
<p><img alt="Yikes dot png" src="https://www.ericlight.com/images/Ramblings/yikes.png"></p>
<p>Realising I was depressed came as quite a shock to me. I've always been the dude who has a smile on his face, laughs at every opportunity, and gets <a href="https://www.adventurealan.com/">super</a> <a href="https://www.xkcd.com/">enthusiastic</a> <a href="https://www.laroma.co.nz/">about</a> <a href="https://www.soba.org.nz/">super</a> <a href="https://sharpologist.com/">niche</a> <a href="https://www.ericlight.com/">things</a>. I was running a reasonably successful business at the time, really enjoyed my work and my colleagues, had a thriving family... It didn't make a whole lot of sense to me. Things were looking good!</p>
<p><img alt="'Stonks' meme, happy man, stocks go up" src="https://www.ericlight.com/images/Ramblings/stonks.png"></p>
<p>In retrospect, all of that was true, but it's only part of the picture. I was exhausted, working at least 60 hours a week, I rarely had real (uninterrupted) time to spend with my family, and there was a huge mental burden knowing that 16 individual lives were reliant on the income that the company created... a company which, though financially "fine", was never financially "flourishing". I'd lost touch with friends, stopped exercising, and wasn't engaging in anything I truly loved. Things were not looking good.</p>
<p><img alt="'Not stonks' meme, sad man, stocks go down" src="https://www.ericlight.com/images/Ramblings/not_stonks.jpg"></p>
<p>Depression was not what I expected. People talk about the "black dog" of depression, and I guess I expected it to be "feeling sad all the time". I rarely felt sad; I just felt numb and disengaged, and it felt like my head was full of mud. Instead of heading off on my mountain bike or making plans for after work, I'd rather sit on the couch and scroll through social media until bedtime arrived. But when I did end up in a social situation, I could easily engage and laugh and chat – enough that nobody suspected how I was feeling. Years later, when I was sharing my experiences with a friend, I described it as "the shine had gone off everything". Disinterested, disengaged, foggy-brained, and no motivation to change any of it. (big note: this is how I felt it, but folks experience depression differently)</p>
<p>What helped me through? Firstly, medication. Antidepressants usually take a full two weeks to kick in, but before long I realised that the general foggy/muddiness of my brain was starting to lift. I could mentally take things in again, and I was a little less detached... enough that I could turn up somewhere voluntarily. Once I was able to actively engage a little, I started exercising a bit. We all know that exercise is a strong antidepressant, but I needed help <em>in order to do that</em>. And the third thing that helped – once I'd been on meds and exercising for a couple months, I had the capacity to visit friends, share stories, and make regular commitments. My mate Russell and I would catch up every Friday at 5pm, cook dinner for our combined families, and then spend hours talking, playing guitar, singing, and just generally enjoying friendship. That connectedness is what I finally needed to recover from depression.</p>
<p>Important note: Everyone is different, and that difference is rarely more pronounced than in mental health. For example, the medication that worked for me may not work for everyone, and medication often doesn't work alone. Friends of mine have tried three or four different types of antidepressants before finding one that helped, and counselling often plays a critical role in recovery.</p>
<p><img alt="Eric and Russell, playing guitars at a picnic table while out camping" src="https://www.ericlight.com/images/Ramblings/russ.jpg">
<figcaption>Ol' Rusty and I, glamping at Athenree Campground, in 2011</figcaption></p>
<p>Connectedness with community and friends is one of our most powerful contributors to happiness and that sense of fulfilment we yearn for. Humans are very social creatures, and it's essential to our wellbeing to engage and bring value to our social circle. We all need to put time into our friendships, our community, and our passions – neglecting these can bring a much greater cost than we expect, and it's hard to dig yourself out once you're in that hole. In fact – your friends and community are critical to pulling you out, which is why opening up and talking about it is so important. We can't help if we don't know.</p>
<p>To finish up this article, I thought I'd share a couple of resources. I went through my depression at the same time as Hyperbole-and-a-Half author Allie, who has a comical story <a href="http://hyperboleandahalf.blogspot.com/2011/10/adventures-in-depression.html">here</a>. A less-silly comic was drawn up by artist Colleen Butters <a href="https://solar-citrus.tumblr.com/post/98583201090/you-would-be-surprised-with-how-many-people-in">here</a>, which I also recommend. <a href="https://thelostconnections.com/">Lost Connections</a> by Johann Hari is an excellent book, bringing together research from the last fifty years, with a focus on social connectivity. And if someone reaches out to you for support, there are some resources on how best to help at the <a href="https://www.mentalhealth.org.nz/get-help/in-crisis/worried-about-someone/">Mental Health Foundation</a></p>
<p>Oh, getting back to the beginning of the story. Of course, my wife replied "Yeah, <em>duh</em>, I've been trying to tell you that for months." ¯\_(ツ)\_/¯</p>Make the Flex theme center images2020-10-07T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2020-10-07:/make-the-flex-theme-center-images.html<p>Previously I've been frustrated that the CSS in the <a href="https://www.getpelican.com">Pelican</a> <a href="https://github.com/alexandrevicenzi/Flex">Flex theme</a> doesn't centre images. However, I'm only one user with one use-case, so I haven't raised a pull request.</p>
<p>Instead, I've finally gotten around to creating a quick-and-dirty sed string to fix the minified CSS file:</p>
<div class="highlight"><pre><span></span><code><span class="err">sed -i 's/}img{max-width:100%}/}img{max-width:100%;margin-left:auto;margin-right:auto;display:block}/' style.min.css</span>
</code></pre></div>
<p>I also like my caption text to be italicised and centered, so I extended this a little: </p>
<div class="highlight"><pre><span></span><code><span class="err">sed -i 's/}img{max-width:100%}/}img{max-width …</span></code></pre></div><p>Previously I've been frustrated that the CSS in the <a href="https://www.getpelican.com">Pelican</a> <a href="https://github.com/alexandrevicenzi/Flex">Flex theme</a> doesn't centre images. However, I'm only one user with one use-case, so I haven't raised a pull request.</p>
<p>Instead, I've finally gotten around to creating a quick-and-dirty sed string to fix the minified CSS file:</p>
<div class="highlight"><pre><span></span><code><span class="err">sed -i 's/}img{max-width:100%}/}img{max-width:100%;margin-left:auto;margin-right:auto;display:block}/' style.min.css</span>
</code></pre></div>
<p>I also like my caption text to be italicised and centered, so I extended this a little: </p>
<div class="highlight"><pre><span></span><code><span class="err">sed -i 's/}img{max-width:100%}/}img{max-width:100%;margin-left:auto;margin-right:auto;display:block}figcaption{font-style:italic;text-align:center}' style.min.css</span>
</code></pre></div>
<p>Run either of those in <code>./Flex/static/stylesheet</code>. It'll modify just the img class in the CSS and suddenly all your images will center unless you tell them not to!</p>Kate Bush - Army Dreamers guitar tab2020-08-30T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2020-08-30:/kate-bush-army-dreamers-guitar-tab.html<p>Some friends and I have been working on our own version of <a href="https://www.youtube.com/watch?v=QOZDKlpybZE">Army Dreamers, by Kate Bush</a>. The original version is replete with instruments, including a prominent Mandolin, some background violins, a synth of some sort, and even the sound of a rifle being racked. Since we're two guitarists, a bassist, and a singer, there's <em>quite a bit</em> of arranging to do to make it work.</p>
<p>Although there's plenty of tab around for the <em>mandolin</em> part, that's only a few notes, with the violin part kicking in immediately afterwards. I …</p><p>Some friends and I have been working on our own version of <a href="https://www.youtube.com/watch?v=QOZDKlpybZE">Army Dreamers, by Kate Bush</a>. The original version is replete with instruments, including a prominent Mandolin, some background violins, a synth of some sort, and even the sound of a rifle being racked. Since we're two guitarists, a bassist, and a singer, there's <em>quite a bit</em> of arranging to do to make it work.</p>
<p>Although there's plenty of tab around for the <em>mandolin</em> part, that's only a few notes, with the violin part kicking in immediately afterwards. I wanted to cover both.</p>
<p>There are four separate phases in it, which I've made up some unimaginative names for:</p>
<ul>
<li>The slide phrase</li>
<li>The downwards walk</li>
<li>The upwards walk</li>
<li>The violin phrase</li>
</ul>
<p>The bar structure runs like this:</p>
<ol>
<li>Slide phrase + violin phrase</li>
<li>Downwards walk + violin phrase</li>
<li>Slide phrase + violin phrase</li>
<li>Upwards walk + violin phrase</li>
</ol>
<p>That structure is then repeated for the entire song. As you can see, the violin phrase is actually dominant, being played at the end of every bar.</p>
<div class="highlight"><pre><span></span><code> The slide phrase The violin phrase Downwards walk phrase Violin phrase again
e|--17/14-14----17/9-9-----9h10p9------------------10----9----10--------------9h10p9----------------|
B|----------------------------------10--------------------------------7----------------10-----------|
G|---------------------------------------9--------------------------------------------------9-------|
D|-------------------------------------------9--------------------------------------------------9---|
A|--------------------------------------------------------------------------------------------------|
E|--------------------------------------------------------------------------------------------------|
The slide phrase The violin phrase The upwards walk phrase Violin phrase again
e|--17/14-14----17/9-9-----9h10p9----------------------------7----9-----------9h10p9----------------|
B|----------------------------------10-------------7----8------------------------------10-----------|
G|---------------------------------------9--------------------------------------------------9-------|
D|-------------------------------------------9--------------------------------------------------9---|
A|--------------------------------------------------------------------------------------------------|
E|--------------------------------------------------------------------------------------------------|
</code></pre></div>Ham and Pea Soup2020-08-09T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2020-08-09:/ham-and-pea-soup.html<p>I've never made Ham and Pea soup before today. I remember my mum making it when I was younger, but it was never really my thing. But tonight just seemed the right combination of a rainy, chilly, wintery evening... and we had some leftover <a href="https://www.ericlight.com/delicious-cornbread.html">jalapeño cornbread</a>!</p>
<p>Well, it was so good I completely forgot to even take photos. I did it all in our pressure cooker, so the meal was ready in about half an hour. Here's what I did:</p>
<h1>Ingredients</h1>
<h3>Primary Aromatics</h3>
<ul>
<li>2 tablespoons butter</li>
<li>5 cloves garlic, chopped …</li></ul><p>I've never made Ham and Pea soup before today. I remember my mum making it when I was younger, but it was never really my thing. But tonight just seemed the right combination of a rainy, chilly, wintery evening... and we had some leftover <a href="https://www.ericlight.com/delicious-cornbread.html">jalapeño cornbread</a>!</p>
<p>Well, it was so good I completely forgot to even take photos. I did it all in our pressure cooker, so the meal was ready in about half an hour. Here's what I did:</p>
<h1>Ingredients</h1>
<h3>Primary Aromatics</h3>
<ul>
<li>2 tablespoons butter</li>
<li>5 cloves garlic, chopped</li>
<li>1 onion, diced</li>
<li>1 shallot, diced (or just use a bigger onion)</li>
</ul>
<h3>Secondary Aromatics</h3>
<ul>
<li>2 carrots, chopped about 1cm square ish</li>
<li>2 celery sticks, chopped about 1cm square ish</li>
<li>2 bay leaves</li>
<li>decent pinch of dried parsley</li>
</ul>
<h3>Body</h3>
<ul>
<li>a bacon hock, circa 800g</li>
<li>500g bag of dried split peas</li>
<li>1/2c red lentils</li>
<li>2.5tsp Vegeta vegetable stock powder</li>
<li>about 6 cups boiling water</li>
</ul>
<h1>Method</h1>
<ol>
<li>Start by putting the peas in the pressure cooker pot, and soaking them in fairly hot water. Then start your prep. </li>
<li>Once the veggies are prepped, drain the peas and set them aside. Rinse the pot, and put it on the stovetop on high.</li>
<li>Add your primary aromatics and fry for 5 minutes, then add the secondary aromatics and fry another 10 minutes.</li>
<li>Remove from stovetop, and put the inner into the pressure cooker body. </li>
<li>Add the peas and lentils to the pot, sprinkle in the vegetable stock, and mix it all together.</li>
<li>Create a depression in the mix, and place the bacon hock in, so it's as low in the pot as possible.</li>
<li>Fill with boiling water until covered, and try to stir it a bit without lifting the hock too much.</li>
<li>Put on lid, and pressure cook for 30 minutes.</li>
</ol>
<p>That's about it! After that it was just a matter of chopping the meat off the hock, stirring it in, and potentially adding a little more water.</p>
<p>It would have been far easier to use a boneless lump of ham instead of the boney bacon hock. If you do this, add some extra stock powder to compensate for the missing salt.</p>
<p>Credit: The recipe above is based on <a href="https://www.allrecipes.com/recipe/219170/ham-and-split-pea-soup-recipe-a-great-soup/">https://www.allrecipes.com/recipe/219170/ham-and-split-pea-soup-recipe-a-great-soup/</a>, with a good few tweaks of my own.</p>Delicious Cornbread2020-07-26T00:00:00+12:002020-08-09T00:00:00+12:00Eric Lighttag:www.ericlight.com,2020-07-26:/delicious-cornbread.html<p>I remember celebrating Christmas with family in New Mexico when I was a kid. I was fairly young, but I think it must have been at the <a href="https://en.wikipedia.org/wiki/Christmas_in_Mexico#Feast_of_the_Virgin_of_Guadalupe">Feast of the Virgin of Guadalupe</a>. One of the most delicious treats I recall from the Feast was real Mexican cornbread.</p>
<p>Now, every few years I'll head into <a href="https://www.gilmours.co.nz/">Gilmours</a> and yoink a three-kilo bag of cornmeal. I don't make this often, but we do all love it, and one batch usually makes enough for multiple households.</p>
<figure align="center">
<img src="https://www.ericlight.com/images/Food/cornbread.jpg" width="400" alt="A cast-iron skillet, hot from the oven, cradling a golden-brown cornbread."/>
<figcaption><em>It really comes out this beautiful every …</em></figcaption></figure><p>I remember celebrating Christmas with family in New Mexico when I was a kid. I was fairly young, but I think it must have been at the <a href="https://en.wikipedia.org/wiki/Christmas_in_Mexico#Feast_of_the_Virgin_of_Guadalupe">Feast of the Virgin of Guadalupe</a>. One of the most delicious treats I recall from the Feast was real Mexican cornbread.</p>
<p>Now, every few years I'll head into <a href="https://www.gilmours.co.nz/">Gilmours</a> and yoink a three-kilo bag of cornmeal. I don't make this often, but we do all love it, and one batch usually makes enough for multiple households.</p>
<figure align="center">
<img src="https://www.ericlight.com/images/Food/cornbread.jpg" width="400" alt="A cast-iron skillet, hot from the oven, cradling a golden-brown cornbread."/>
<figcaption><em>It really comes out this beautiful every time.</em></figcaption>
</figure>
<p>I always cook this in a cast-iron skillet, because it allows me to fry off the butter a bit first - this adds a nice roasty nutty flavour.</p>
<h1>Ingredients</h1>
<h3>Delicious fat</h3>
<ul>
<li>120g (half a cup) of butter</li>
</ul>
<h3>Dry ingredients</h3>
<ul>
<li>1.5 cups cornmeal</li>
<li>1.5 cups other flour (mix & match anything to add up to 1.5c; just avoid self-raising)</li>
<li>2.5 tsp baking powder</li>
<li>2 tsp salt</li>
<li>1 cup brown sugar</li>
</ul>
<p>The 'other flour' component is super flexible - as long as it's dry dust, it hardly seems to matter what you use. Rice flour could make this gluten free, or wholemeal to make it gut-friendly, or tapoica flour if you just ... need to use up some random tapioca flour you bought over lockdown for some reason.</p>
<p>In fact, the cornbread in the oven <em>right now</em> has some psyllium husk, to try and keep the moisture locked in. (Update: the psyllium was <strong>awesome</strong>! Substituted 1Tbsp for random flour.)</p>
<h3>Wet ingredients</h3>
<ul>
<li>3 eggs, room temperature</li>
<li>1.5 cups milk, room temperature</li>
</ul>
<h1>Method</h1>
<ol>
<li>You forgot to warm up your eggs and milk, so pop your milk into the microwave for a minute, and stick the eggs in a bowl of warm water.</li>
<li>Turn your oven to 180°C, then pop the butter in your skillet and get it melting over low heat.</li>
<li>Mix your dry ingredients in a mixing bowl. In different (larger) mixing bowl, whisk together the eggs and milk.</li>
<li>Add the dry ingredients to the wet ones, folding gently. Now you can just dust the flour out of that bowl and put it away! (<em>Life haxx</em>)</li>
<li>Your butter should be a nice nutty brown by now; carefully pour it into your batter - keep just a tiny bit in the pan for non-stickness.</li>
<li>Give everything a gentle stir, and pour the batter into the skillet.</li>
<li>Into the oven it goes! Cook until a toothpick comes out clean, approx 20~30 minutes.</li>
</ol>
<figure align="center">
<img src="https://www.ericlight.com/images/Food/cornbread-action.jpg" width="400" alt="Steaming-hot, soft cornbread, slumbering contentedly on a chopping board. A lazy dollop of butter melts upon the brown crust. In the distance, trumpets."/>
<figcaption><em>Yum.</em></figcaption>
</figure>
<h1>Jalapeño Update</h1>
<p>Today I tried some jalapeño and cheese in the cornbread. It was easily the best cornbread I've made so far! </p>
<p>As above, except with the following modifications:</p>
<ul>
<li>Increase salt to 2.5tsp</li>
<li>Reduce sugar to a half cup</li>
<li>2~2.5 cups of grated cheese</li>
<li>About 1/3 cup of chopped jalapeño</li>
</ul>
<p>The cheese and jalapeño go into the batter after the butter is mixed in - just before you pour it into the skillet.</p>
<p>Today's cheese was about 1.5 cups of grated Colby, and another half cup of grated parmesan to add a bit of sharpness. It wasn't <em>quite</em> enough, so next time I'll either increase the proprtion of parmesan to 2/3c, or use a slightly sharper base cheese.</p>
<figure align="center">
<img src="https://www.ericlight.com/images/Food/cornbread-cheese.jpg" width="400" alt="The jalapeño and cheese on the chopping board, ready to be introduced to the batter"/>
<figcaption><em>The cheese and jalapeño ready for the pan!</em></figcaption>
</figure>
<p>Credit: The recipe above is almost entirely from <a href="https://cookieandkate.com/honey-butter-cornbread-recipe/">https://cookieandkate.com/honey-butter-cornbread-recipe/</a>, however I've made a few small tweaks.</p>I made Salmon Gravlax!2020-07-11T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2020-07-11:/i-made-salmon-gravlax.html<p>I joined some friends last weekend for a belated World Whisky Day celebration. The entry fee was, of course, a bottle of whisky (this year the theme was different finishing casks)... but we also each bring some delicious morsel that piques our interest.</p>
<p>This year, as I was bringing <a href="https://www.glenmorangie.com/en-gb/our-whiskies/the-lasanta">Glenmorangie's The Lasanta</a> (aged in Oloroso and Pedro Ximénez sherry casks), I decided my amuse-bouche would be sherry-based.</p>
<p>My treat was dried prunes, soaked in a dry sherry, then sprinkled with a pinch of salt, and eaten with a tamari-roasted almond …</p><p>I joined some friends last weekend for a belated World Whisky Day celebration. The entry fee was, of course, a bottle of whisky (this year the theme was different finishing casks)... but we also each bring some delicious morsel that piques our interest.</p>
<p>This year, as I was bringing <a href="https://www.glenmorangie.com/en-gb/our-whiskies/the-lasanta">Glenmorangie's The Lasanta</a> (aged in Oloroso and Pedro Ximénez sherry casks), I decided my amuse-bouche would be sherry-based.</p>
<p>My treat was dried prunes, soaked in a dry sherry, then sprinkled with a pinch of salt, and eaten with a tamari-roasted almond. They were quite delicious - you only want to soak them for 5 hours or so though, they do go mushy. The salt is critically important; I'm not sure about the tamari, plain almonds may have been just as good.</p>
<p>Anyway, although my treat was great, it paled in comparison to one of the other treats - an amazing fresh salmon gravlax. I'd never heard of gravlax before, but it's actually just a method of curing salmon - sit it in a casing of sugar, salt, and dill for a couple days and it's done! Of course, I had to try it.</p>
<figure align="center">
<img src="https://www.ericlight.com/images/Food/gravlax-boat.jpg" width="400" alt="My hand, holding a slice of gravlax salmon which was way too thick."/>
<figcaption><em>My first introduction to salmon gravlax.</em></figcaption>
</figure>
<p>The recipe below has a couple tweaks, and it's taken almost entirely from <a href="https://www.recipetineats.com/cured-salmon-gravlax/">https://www.recipetineats.com/cured-salmon-gravlax/</a>.</p>
<h1>Comments</h1>
<ul>
<li>For the salmon, skin on or off doesn't matter. I did mine skin-on, and it's a little annoying - next time I'll take it off.</li>
<li>The larger the salt granules, the better. I used <a href="https://mrsrogers.co.nz/product/himalayan-pink-salt-bag/">this Himalayan rock salt</a>. Avoid iodised salt, apparently.</li>
<li>Prefer bigger sugar granules, too - probably not coffee crystals, but raw sugar worked really nicely. Avoid icing sugar or caster sugar.</li>
<li>Use peppercorns if you can; they're fresher than pre-ground. If using pre-ground, add a bit extra. I used <a href="https://mrsrogers.co.nz/product/gourmet-peppercorns-bag/">these ones</a>.</li>
<li>Curing time is tricky. I did mine for 86 hours and it was definitely a hard-cure, but was still really good. I imagine the whisky weekend version had only been a 48-hour cure.</li>
</ul>
<h1>Ingredients</h1>
<ul>
<li>Salmon (de-boned)</li>
<li>Salt & Sugar (ratio below)</li>
<li>Pepper (about 2tsp per 500g salmon)</li>
<li>Dill (optional - about 25g per 500g salmon)</li>
<li>Coriander seeds (optional - about 2tsp per 500g salmon)</li>
<li>Grated lemon rind (optional - about a lemon's worth per 500g salmon)</li>
</ul>
<h1>Method</h1>
<ol>
<li>Bruise your dill, crush your peppercorns, whack your coriander seeds, and grate your lemon rind</li>
<li>Mix your cure. I used a recipe of 4:1:1 (fish:sugar:salt), but next time I'm doing 5:1:1.</li>
<li>Once your cure is mixed, fold in your spices and aromatics.</li>
<li>Spread out half of your cure, lay the salmon on top, and then spread the rest of the cure on top.</li>
<li>Bag it up! I used a vacuum sealer, but a sandwich bag or some plastic wrap will do the trick.</li>
<li>Pop it in the fridge with a weight on it (people recommend a plate).</li>
<li>Flip it over every 12-24 hours. Be careful - a lot of liquid will come out during the curing process!</li>
<li>Once you've cured it for 24-72+ hours, pull it out and gently rinse off all the clumps of dill/pepper/salt etc.</li>
<li>Wrap it in a paper towel to dry it off, then leave it unwrapped in the fridge for a few hours to finish drying out.</li>
<li>Enjoy! Slice it with a nice sharp knife. I'm told it should be sliced "thin enough to read a newspaper through".</li>
</ol>
<figure align="center">
<img src="https://www.ericlight.com/images/Food/gravlax-salted.jpg" width="400" alt="A slice of salmon, so covered in salt, sugar, and dill that the fish itself is invisible. Ready to be bagged."/>
<figcaption><em>All ready to go into the vacuum sealer</em></figcaption>
</figure>
<h1>Other thoughts</h1>
<ul>
<li>I've seen recipes that use aquavit... So next time I'm actually going to try a few tablespoons of gin!</li>
<li>The 4:1:1 ratio wasn't bad - it's just that I ended up pouring out lots of big chunks of salt, so I think it was unnecessary wastage.</li>
<li>I've didn't try coriander in this batch, but I'm super-keen to try it in the next one. I've also seen recipes use juniper berries, which is what made me think of the gin.</li>
<li>What to eat with gravlax? We had it on a platter that also contained seed crackers, a couple cheeses, fruit paste, salami, capers, and pickled gherkins. The capers were great.</li>
</ul>
<figure align="center">
<img src="https://www.ericlight.com/images/Food/gravlax-action.jpg" width="560" alt="Action shot! Thinly-sliced salmon gravlax, whisky-cured pickled gherkins, avocado toast, and mulled wine."/>
<figcaption><em>Things got way too fancy, with the gravlax, some avocado toast, and mulled wine.</em></figcaption>
</figure>My mountain2020-06-06T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2020-06-06:/my-mountain.html<p><img alt="Landscape photography of Mount Tongariro and Mount Ngauruhoe, covered in white snow" src="https://www.ericlight.com/images/tongariro.jpg"></p>
<p>I got a tattoo a couple years ago, which is a sketch outline of Mount Tongariro and Mount Ngauruhoe, in the Central Plateau of New Zealand.</p>
<p>The photo that the tattoo, which the tattoo was based on, was just the result of a Google search. I've tried to find it many times since I actually got the tattoo - at very least just so I could give credit to the photographer. However, to no avail.</p>
<p>The other day I happily found a copy of the photo, and went to Google's Reverse …</p><p><img alt="Landscape photography of Mount Tongariro and Mount Ngauruhoe, covered in white snow" src="https://www.ericlight.com/images/tongariro.jpg"></p>
<p>I got a tattoo a couple years ago, which is a sketch outline of Mount Tongariro and Mount Ngauruhoe, in the Central Plateau of New Zealand.</p>
<p>The photo that the tattoo, which the tattoo was based on, was just the result of a Google search. I've tried to find it many times since I actually got the tattoo - at very least just so I could give credit to the photographer. However, to no avail.</p>
<p>The other day I happily found a copy of the photo, and went to Google's Reverse Image Search to figure out where it had come from! The answer is...</p>
<p>... nowhere. Whoever posted the image way-back-when appears to have taken the photo down. The Mighty Goog can't find it anywhere.</p>
<p>So, here we are I guess. I'm uploading the photo here so I don't lose it again. If you took this photo, or if you know who did, please contact me!</p>ZFS zpool vanishing after upgrading ProxmoxVE 5.4 to 6.22020-05-23T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2020-05-23:/zfs-zpool-vanishing-after-upgrading-proxmoxve-54-to-62.html<p>Performing a major version upgrade is never pleasant. I've been using ProxmoxVE for about ten years now though, and it's consistently done a fantastic job. Since it's based on Debian, all the upgrades are done with a simple <code>apt update && apt upgrade</code>, with a variety of steps in the middle to point to new repositories, etc. Nothing out of the ordinary, nothing scary.</p>
<p>So I've got two servers - one is an old one, with only a couple testing VM's residing on it. I go ahead and work through the <a href="https://pve.proxmox.com/wiki/Upgrade_from_5.x_to_6.0">5 …</a></p><p>Performing a major version upgrade is never pleasant. I've been using ProxmoxVE for about ten years now though, and it's consistently done a fantastic job. Since it's based on Debian, all the upgrades are done with a simple <code>apt update && apt upgrade</code>, with a variety of steps in the middle to point to new repositories, etc. Nothing out of the ordinary, nothing scary.</p>
<p>So I've got two servers - one is an old one, with only a couple testing VM's residing on it. I go ahead and work through the <a href="https://pve.proxmox.com/wiki/Upgrade_from_5.x_to_6.0">5.x to 6.x upgrade guide</a>, and everything Just Works. No problem with that one.</p>
<p>When I moved onto the other server I had a couple different things I noticed. For example, when trying to upgrade Corosync 2.x to 3.x (a prerequisite for the OS upgrade), I noticed it was trying to uninstall things like <code>corosync-pve</code>, which <em>really</em> didn't seem right.</p>
<p>After comparing <code>dpkg -l</code> contents between the two servers, I learned that <code>corosync-pve</code> is actually just a transitional package - completely replaced by the new <code>corosync</code> package in version 3. And although the server was trying to uninstall <code>corosync-pve</code>, it was then immediately installing <code>corosync</code>... so no problem.</p>
<p>Things continued to be mildly alarming during the upgrade itself, but not actually toooo bad, as all the removed packages were being replaced. This one, for example:</p>
<div class="highlight"><pre><span></span><code>dpkg: pve-libspice-server1: dependency problems, but removing anyway as you requested:
pve-qemu-kvm depends on pve-libspice-server1 (>= 0.12.5-1); however:
Package pve-libspice-server1 is to be removed.
spiceterm depends on libspice-server1 (>= 0.12.2); however:
Package libspice-server1 is not installed.
Package pve-libspice-server1 which provides libspice-server1 is to be removed.
(Reading database ... 65255 files and directories currently installed.)
Removing pve-libspice-server1 (0.14.1-2) ...
</code></pre></div>
<p>... was replaced with <code>spiceterm</code>. No worries.</p>
<p>However things went <em>sharply downhill</em> following reboot. All of my VM images were missing! I had a ZFS zpool that should have been at <code>/VM_Local_zpool</code> - that folder <em>existed</em>, and contained an <code>./images</code> folder, but that was completely empty.</p>
<p>I quickly checked the storage information in Proxmox, and the result was... <strong>not good</strong>:</p>
<figure align="center">
<img src="https://www.ericlight.com/images/Tech/lost_zpool.png" alt="My storage usage - consistently at about 1.2 terabytes, and then suddenly... zero."/>
</figure>
<p>... Really, not good. :-|</p>
<p>So I SSH'ed into the server and had a quick look at my list of ZFS stores, and discovered that my dataset was entirely absent: </p>
<div class="highlight"><pre><span></span><code># zfs list
NAME USED AVAIL REFER MOUNTPOINT
rpool 83.8G 23.8G 96K /rpool
rpool/ROOT 3.65G 23.8G 96K /rpool/ROOT
rpool/ROOT/pve-1 3.65G 23.8G 3.65G /
rpool/data 71.6G 23.8G 71.6G /rpool/data
rpool/swap 8.50G 25.4G 6.85G -
# zpool list
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
rpool 111G 82.1G 28.9G - - 66% 73% 1.00x ONLINE -
</code></pre></div>
<p>A bit of Googling led me to the <code>zfs import</code> command, which resulted in the first piece of good news of the night:</p>
<div class="highlight"><pre><span></span><code># zpool import
pool: VM_Local_zpool
id: 6614373363984244305
state: ONLINE
status: Some supported features are not enabled on the pool.
action: The pool can be imported using its name or numeric identifier, though
some features will not be available without an explicit 'zpool upgrade'.
config:
VM_Local_zpool ONLINE
mirror-0 ONLINE
wwn-0x50014ee0aeee96ef ONLINE
wwn-0x50014ee05998ee25 ONLINE
</code></pre></div>
<p>It exists! And it's ... online? But where? I don't get it. I went ahead and tried importing it, but got a "directory not empty" error:</p>
<div class="highlight"><pre><span></span><code># zpool import VM_Local_zpool
cannot mount '/VM_Local_zpool': directory is not empty
</code></pre></div>
<p>Now, <em><strong>if</strong> I'd been paying attention</em> there, I would have realised that <code>zpool list</code> now contained my VM_Local_zpool:</p>
<div class="highlight"><pre><span></span><code># zfs list
NAME USED AVAIL REFER MOUNTPOINT
VM_Local_zpool 1.16T 611G 1.16T /VM_Local_zpool
rpool 83.8G 23.8G 96K /rpool
rpool/ROOT 3.65G 23.8G 96K /rpool/ROOT
rpool/ROOT/pve-1 3.65G 23.8G 3.65G /
rpool/data 71.6G 23.8G 71.6G /rpool/data
rpool/swap 8.50G 25.4G 6.85G -
</code></pre></div>
<p>From this point, all I had to do was empty /VM_Local_zpool, and try to remount the zpool. But there's a second trick here.</p>
<p>ProxmoxVE has a pretty clear idea of How Storage Should Look, so every time it scans a storage device, is makes sure there's an <code>./images</code> folder in any storage enabled for VM Images. It also makes sure there's a <code>./dump</code> folder on any storage enabled as a backup target, and a <code>./template</code> folder on any storage enabled for ISO images. (Reference: <a href="https://pve.proxmox.com/wiki/Storage:_Directory">https://pve.proxmox.com/wiki/Storage:_Directory</a>)</p>
<p>So, when I removed that /VM_Local_zpool/images folder, Proxmox just... went ahead and recreated it almost immediately, so I still couldn't mount the zpool there.</p>
<p>In the end, I managed to get my zpool remounted by pairing the <code>rmdir</code> and <code>mount</code> commands together on the same line:</p>
<div class="highlight"><pre><span></span><code># rmdir /VM_Local_zpool/images/
# zfs mount VM_Local_zpool
cannot mount '/VM_Local_zpool': directory is not empty
# rmdir /VM_Local_zpool/images/ && zfs mount VM_Local_zpool
# cd VM_Local_zpool/
/VM_Local_zpool# ls
backup images
</code></pre></div>
<p>... and there we go! My mount point, and all my VM images, are back unscathed!</p>
<p>And just for future reference - I saw a post on the FreeNAS forums that I should the status of the zfs-import-cache service, and enable it if it wasn't started by default... however it was fine:</p>
<div class="highlight"><pre><span></span><code># systemctl status zfs-import-cache.service
● zfs-import-cache.service - Import ZFS pools by cache file
Loaded: loaded (/lib/systemd/system/zfs-import-cache.service; enabled; vendor preset: enabled)
Active: active (exited) since Sat 2020-05-23 20:46:54 NZST; 3min 26s ago
Docs: man:zpool(8)
Process: 1819 ExecStart=/sbin/zpool import -c /etc/zfs/zpool.cache -aN (code=exited, status=0/SUCCESS)
Main PID: 1819 (code=exited, status=0/SUCCESS)
May 23 20:46:54 ~ systemd[1]: Starting Import ZFS pools by cache file...
May 23 20:46:54 ~ zpool[1819]: no pools available to import
May 23 20:46:54 ~ systemd[1]: Started Import ZFS pools by cache file.
</code></pre></div>Why are all Split-Tunnel VPN diagrams so ugly?2020-05-21T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2020-05-21:/why-are-all-split-tunnel-vpn-diagrams-so-ugly.html<p>Right.</p>
<p>Today I needed to find a diagram of the traffic flow for a split-tunnel VPN. Nothing fancy, just a real simple user-facing diagram to form part of an article.</p>
<p>And friends, there was <em>nothing</em>. Nothing at all. I found proper technical ones from <a href="https://documentation.meraki.com/@api/deki/files/721/c6ddeaa8-5df4-4e5e-b542-c52766568816?revision=1">Cisco Meraki</a>; fancy Office365 ones, depicting an <a href="https://docs.microsoft.com/en-us/office365/enterprise/media/vpn-split-tunneling/vpn-model-2.png">ExpressRoute to O365</a> and tunnelling everything <em>else</em> through the VPN; and another Office365 tunnel with <a href="https://docs.microsoft.com/en-us/office365/enterprise/media/vpn-split-tunneling/vpn-model-5.png">ExpressRoute and a split-tunnel</a> for the rest of the traffic.</p>
<p>Pretty much the closest I came to my needs was this atrocity, via <a href="http://blog.soundtraining.net/2013/03/how-to-configure-split-tunneling-on.html">http …</a></p><p>Right.</p>
<p>Today I needed to find a diagram of the traffic flow for a split-tunnel VPN. Nothing fancy, just a real simple user-facing diagram to form part of an article.</p>
<p>And friends, there was <em>nothing</em>. Nothing at all. I found proper technical ones from <a href="https://documentation.meraki.com/@api/deki/files/721/c6ddeaa8-5df4-4e5e-b542-c52766568816?revision=1">Cisco Meraki</a>; fancy Office365 ones, depicting an <a href="https://docs.microsoft.com/en-us/office365/enterprise/media/vpn-split-tunneling/vpn-model-2.png">ExpressRoute to O365</a> and tunnelling everything <em>else</em> through the VPN; and another Office365 tunnel with <a href="https://docs.microsoft.com/en-us/office365/enterprise/media/vpn-split-tunneling/vpn-model-5.png">ExpressRoute and a split-tunnel</a> for the rest of the traffic.</p>
<p>Pretty much the closest I came to my needs was this atrocity, via <a href="http://blog.soundtraining.net/2013/03/how-to-configure-split-tunneling-on.html">http://blog.soundtraining.net/2013/03/how-to-configure-split-tunneling-on.html</a>:</p>
<figure align="center">
<img src="https://www.ericlight.com/images/Security/split_tunnel_yes.jpg" alt="An accurate, but not aesthetic, diagram of how split tunnels work." width="300"/>
<figcaption><em>Although accurate and functional, this is not a pleasant sight.</em></figcaption>
</figure>
<p>So I went over to <a href="https://www.draw.io">https://www.draw.io</a> and whipped up something a bit prettier. This isn't marvelous, but it's way better than I could find anywhere else:</p>
<figure align="center">
<img src="https://www.ericlight.com/images/Security/split_tunnel_better.png" alt="A slightly more pleasant diagram of how split tunnels work."/>
</figure>
<p>In retrospect, I could have done better - I really should have had the corporate tunnel going <strong>through</strong> the cloud of the internet. However this works for ne.</p>
<p>If you'd like to use this, feel free. You can even use <a href="https://app.diagrams.net/?lightbox=1&highlight=0000ff&edit=_blank&layers=1&nav=1&title=VPN%20Split%20Tunnel(2).drawio#R7Vddb5swFP01PCbCfCV5XJKmU9VKrSp1W1%2BQAzdgxWBkTCD99TPFTiCwtZMSdZWqRMI%2B9%2Foa33Nscw17kVTXHGfxHQuBGpYZVoa9NCwLOZZl1H8z3DeIN7MbIOIkbCDzCDySF1AjNVqQEHKFNZBgjAqSdcGApSkEooNhzlnZddswGnaADEfQAx4DTPvoDxKKWKGe6xwN34FEsZ4aebPGkmDtrZaSxzhkZSusfWXYC86YaFpJtQBaZ6%2BbmNUfrIc345CK9wy4dZ9vls8%2F4e7p9uEO3QTldTQaKTZ2mBZqxeplxV6nIGMkFcCvdnKeOpvIsOeHtZiyE%2BI8hlB1YpFQ7SQ428KCUcYlkrJUBpxvCKUaMizbNeufxCleA71nORGEpdIWQD2pNOyACyIJuT1xWDMhWNJy%2BEZJVBsEyyTKCkFJKmfXuqgnwcrlEFyuI6uXmVRRrd8x22xIAOMQdvKRj0vGt7nAzYzzfsIVB%2FUbQHXKrNwTwBIQfC9dlNX2lBjUdrBnql8exaV3SNySlXbDSs7RIfKRcNlQnP8D%2F84F%2Bf%2BvKM2By6i5evobzJO%2BGlerqWOaPem2LWcQgTc9EcG0LwJkeX0VIHQpGUy%2BjoFBzQQFJ2I%2FpizY%2BiURsb%2BFva9hf%2F2arXNIwnVOz4VpTxL66GgrYuJcSBCzzy%2BIQeqHVfJeQQSUFWE%2Bzoo1JYH%2F2jsP%2F84MdfiXX079I2EyIABkowspQJ81n1kCF7xHRCFHU18uBDdszDnTXwrLEZqe6a5wJt2DwXH6d4U7G9DFpW4KhL5k8fGy8NDHyYK%2F4EfysCrTnefSp8p9iX%2FxkfW2KnTmNhSqb3VpJlMBaaiay4DiPCdBVxDSrssuNG36qkZ0x7b1t1wKzCMQb99wEHYKwH7G2xkdOIA1xoFKmnfdsnEozWqG%2B3qPtPa55XQJNb1uiJwVPAA1ql3lnQaadAPZ7kmgJjG9QK%2BsH5Y9JATZPRarjfux5revfgM%3D">this fancy URL</a> to open the drawing as an editable vector graphic at <a href="https://www.draw.io">Draw.io</a> directly!</p>Roundcube not loading email contents2020-05-11T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2020-05-11:/roundcube-not-loading-email-contents.html<p>Here's another quick one! I had a <a href="https://roundcube.net">Roundcube</a> instance, chugging along fine. Then one day it just stopped loading emails! Everything else was all fine - no problems with login etc, but trying to preview an email just game me a sadfaec. Chrome couldn't load the contents, and told me that the server had refused to connect.</p><p>Here's another quick one! I had a <a href="https://roundcube.net">Roundcube</a> instance, chugging along fine.</p>
<p>Then one day it just stopped loading emails! Everything else was all fine - no problems with login etc, but trying to preview an email just game me a sadfaec. Chrome couldn't load the contents, and told me that the server had refused to connect:</p>
<figure align="center">
<img src="https://www.ericlight.com/images/Tech/roundcube.png" alt="Roundcube webmail - everything looks perfect, except there's a error loading the preview of the selected email."/>
</figure>
<p>So of course, I can't just let this go - being able to see the contents of the emails is relatively important! But what the heck was causing it?</p>
<p>I spent some time in Chrome's developer tools and console, as well as time grepping and tailing log files... this would have all been fixed much earlier if I were running Firefox I think, as it's a bit more explicit with errors.</p>
<p>So, what was the fix? It was nothing to do with Roundcube, routing, firewalls, or reverse proxies. (Seriously, I checked all of these...)</p>
<p>The problem is that, last week, I'd modified the HTTP Headers on the reverse proxy to include:</p>
<div class="highlight"><pre><span></span><code><span class="err"> X-Frame-Options ("DENY")</span>
</code></pre></div>
<p>... no good. It all came right when I changed the X-Frame-Options directive to "SAMEORIGIN". Suddenly, all fixed.</p>
<p>Sheesh!</p>Renaming a computer object in Active Directory2020-05-09T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2020-05-09:/renaming-a-computer-object-in-active-directory.html<p>Quick post tonight.</p>
<p>You can't rename a computer object in Active Directory Users and Computers. Even if you change the hostname, the domain object will still have the original distinguishedName from the old device.</p>
<p>However... you can do it in ADSIEdit! Just open <code>ADSIEdit</code>, navigate to the AD container that holds your misnamed object, right click on it, and Rename.</p>
<p>I've just done it with a couple test computers on a domain and both worked completely smoothly. I don't know if this would be safe if the renamed computer were …</p><p>Quick post tonight.</p>
<p>You can't rename a computer object in Active Directory Users and Computers. Even if you change the hostname, the domain object will still have the original distinguishedName from the old device.</p>
<p>However... you can do it in ADSIEdit! Just open <code>ADSIEdit</code>, navigate to the AD container that holds your misnamed object, right click on it, and Rename.</p>
<p>I've just done it with a couple test computers on a domain and both worked completely smoothly. I don't know if this would be safe if the renamed computer were off-site.</p>WireGuard on Windows - Part 22020-05-08T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2020-05-08:/wireguard-on-windows-part-2.html<p>A few days ago I spun up a <a href="https://www.ericlight.com/setting-up-a-windows-dev-vm-under-proxmoxve.html">Windows Dev VM</a> to have a play with <a href="https://www.wireguard.com/install/">WireGuard for Windows</a>.</p>
<p>I didn't really have a clear goal in mind when I started playing with this - part of it was in trying to create and launch a tunnel without using the GUI. Mostly I was just trying to learn more about a new implementation of a tool that I really like.</p>
<p>If you read my <a href="https://www.ericlight.com/getting-wireguard-on-windows-quietly.html">previous article</a>, you'll recall that I started off trying to do this with just <code>wireguard.exe</code>. Here …</p><p>A few days ago I spun up a <a href="https://www.ericlight.com/setting-up-a-windows-dev-vm-under-proxmoxve.html">Windows Dev VM</a> to have a play with <a href="https://www.wireguard.com/install/">WireGuard for Windows</a>.</p>
<p>I didn't really have a clear goal in mind when I started playing with this - part of it was in trying to create and launch a tunnel without using the GUI. Mostly I was just trying to learn more about a new implementation of a tool that I really like.</p>
<p>If you read my <a href="https://www.ericlight.com/getting-wireguard-on-windows-quietly.html">previous article</a>, you'll recall that I started off trying to do this with just <code>wireguard.exe</code>. Here are some things I've discovered:</p>
<h3>wireguard.exe does a <em>whole lot</em> of stuff</h3>
<p>Wireguard.exe isn't just a GUI, which I originally thought it was. It's also the piece of software that shouts out to <a href="https://www.wintun.net/">WinTun</a> to create the interface, as well as the utility that reads the 'extended' attributes in your .conf file (e.g. the stuff that wg-quick takes care of), as well as the utility that <a href="https://github.com/WireGuard/wireguard-windows/blob/master/tunnel/addressconfig.go">sets up your routes, DNS</a>, etc, etc, etc.</p>
<h3>wireguard.exe doesn't create private/public keypairs</h3>
<p>... To do this, you instead need to use wg.exe, which is installed under your System32 folder (so it's in your path, so it's accessible anywhere):</p>
<div class="highlight"><pre><span></span><code>PS C:\> wg genkey | tee $ENV:APPDATA\WireGuard.priv | wg pubkey > $ENV:APPDATA\WireGuard.pub
</code></pre></div>
<p>I did <a href="https://www.ericlight.com/getting-wireguard-on-windows-quietly.html">figure this out the other day</a>, but I'm reiterating here.</p>
<h3>wg.exe can read .conf files -- but you don't really want it to</h3>
<p>Last time, I was having trouble reading a .conf file from wg.exe:</p>
<div class="highlight"><pre><span></span><code>PS C:\Users> wg setconf wg0 .\wg0.conf
Line unrecognized: ` ■['
Configuration parsing error
</code></pre></div>
<p>I'm not entirely sure what this was - I've since been able to read in a .conf file perfectly fine (for the record this is UTF-8 with Windows CRLF line-endings). </p>
<p>However ... my breakthrough kinda sucks.</p>
<p>Wireguard for Windows stores it's config files in the Windows DPAPI-encrypted vault. This is <strong><em>vastly</em></strong> better than just bunging a file in <code>C:\Users\Blah</code> and hoping for the best. Maybe it's not perfect - I don't know much about DPAPI - but it's a far cry better than nothing.</p>
<p>When you use wireguard.exe to import a tunnel from a .conf file, it will read it in, sanity-check it (mine failed because I accidentally hit the keyboard during copy/pasta, so it rejected the Base64 encoding), and then safely store it away in the DPAPI storage. You can then delete your original .conf file. Just do this, it's better.</p>
<h3>You need <strong>both</strong> wireguard.exe and wg.exe</h3>
<p>OK so here's the bit that I only fully realised tonight: wireguard.exe is like wg-quick, but it also provides the interface into the <a href="https://github.com/WireGuard/wireguard-windows/blob/master/tunnel/service.go">Windows network stack</a> and the <a href="https://github.com/WireGuard/wireguard-windows/blob/master/conf/store.go">Windows DPAPI storage</a> of your sensitive conf files. You can't even run <code>wg set</code> without it, because wireguard.exe <a href="https://github.com/WireGuard/wireguard-windows/blob/master/manager/ipc_server.go">is even responsible for creating the IPC Server</a> that interfaces with WinTun.</p>
<p>Honestly the Windows world is so much more complicated than the Linux world*. 🙄</p>
<p>(* some caveats apply)</p>
<h2>Conclusion</h2>
<p>What's my plan now?</p>
<p>I'm going to make a thing that:</p>
<ul>
<li>Installs wireguard.msi silently</li>
<li>Uses wg.exe to create a private/public keypair</li>
<li>Uses that keypair to create a temporary .conf file</li>
<li>Uses wireguard.exe to import that .conf file from some predetermined location</li>
<li>Deletes the .conf file (probably using <a href="https://support.microsoft.com/en-nz/help/814599/how-to-use-cipher-exe-to-overwrite-deleted-data-in-windows-server-2003">cipher.exe</a> to scrub it)</li>
<li>Uses wireguard.exe to install the tunnel so it opens automatically on login</li>
</ul>
<p>I'm hoping that this will create us something like an always-on-VPN connection that can be deployed easily by an IT support person, and require no end-user interaction.</p>Getting WireGuard on Windows - quietly2020-04-27T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2020-04-27:/getting-wireguard-on-windows-quietly.html<p>So, I mentioned in my post <a href="https://www.ericlight.com/setting-up-a-windows-dev-vm-under-proxmoxve.html">yesterday</a> that I'm trying to get a bit of a quiet installer for WireGuard on Windows. Not that the current one is <em>noisy</em>, but I have a really simple use-case that I want to meet.</p>
<p>I spent some time seeing if I could just extract <code>WireGuard.exe</code> and run that. Nope, of course - it requires <a href="https://www.wintun.net/">WinTun</a> to be installed to facilitate the Layer 3 tunneling.</p>
<p>Next I played with the idea of just deploying WinTun directly, without installing the WireGuard package itself. I can …</p><p>So, I mentioned in my post <a href="https://www.ericlight.com/setting-up-a-windows-dev-vm-under-proxmoxve.html">yesterday</a> that I'm trying to get a bit of a quiet installer for WireGuard on Windows. Not that the current one is <em>noisy</em>, but I have a really simple use-case that I want to meet.</p>
<p>I spent some time seeing if I could just extract <code>WireGuard.exe</code> and run that. Nope, of course - it requires <a href="https://www.wintun.net/">WinTun</a> to be installed to facilitate the Layer 3 tunneling.</p>
<p>Next I played with the idea of just deploying WinTun directly, without installing the WireGuard package itself. I can only assume that this would have been <em>super easy</em> if I'd ever built a proper MSI installer before, but in the end it was just way easier to:</p>
<div class="highlight"><pre><span></span><code>WireGuard-amd64-0.1.0.msi /q
</code></pre></div>
<p>... It was still worth the tangential digging, but who would have ever guessed that <a href="https://www.zx2c4.com/">Jason Donenfeld</a> would have already done things the best way. ¯\_(ツ)_/¯ </s></p>
<p>Note you've got to run the above in an elevated command prompt, since it's installing drivers. However, the installation is still not quiet - after install, it pops up the WireGuard GUI window!</p>
<figure align="center">
<img src="https://www.ericlight.com/images/Tech/WireGuard_launch.png" alt="After running the installer with the 'Quiet' parameter, the WireGuard GUI still opens"/>
</figure>
<p>"That's annoying," I think to myself, "can I stop that?" To the <a href="https://github.com/WireGuard/WireGuard-windows/blob/master/installer/WireGuard.wxs">installer source code</a>!</p>
<p>OwO ... Hwat's this? </p>
<div class="highlight"><pre><span></span><code> <span class="c"><!--</span>
<span class="c"> Launch WireGuard.exe after setup complete</span>
<span class="c"> --></span>
<span class="nt"><CustomAction</span> <span class="na">Id=</span><span class="s">"LaunchApplication"</span> <span class="na">HideTarget=</span><span class="s">"yes"</span> <span class="na">Impersonate=</span><span class="s">"no"</span> <span class="na">Execute=</span><span class="s">"deferred"</span> <span class="na">FileKey=</span><span class="s">"WireGuard.exe"</span> <span class="na">ExeCommand=</span><span class="s">""</span> <span class="na">Return=</span><span class="s">"asyncNoWait"</span> <span class="nt">/></span>
<span class="nt"><InstallExecuteSequence></span>
<span class="nt"><Custom</span> <span class="na">Action=</span><span class="s">"LaunchApplication"</span> <span class="na">Before=</span><span class="s">"InstallFinalize"</span><span class="nt">></span>(<span class="ni">&amp;</span>WireGuardFeature = 3) AND NOT DO_NOT_LAUNCH<span class="nt"></Custom></span>
<span class="nt"></InstallExecuteSequence></span>
</code></pre></div>
<p>It appears that we can pass through an environment variable to stop the installer from launching the GUI after install!</p>
<div class="highlight"><pre><span></span><code> <span class="p">.\</span><span class="n">WireGuard-amd64</span><span class="p">-</span><span class="n">0</span><span class="p">.</span><span class="n">1</span><span class="p">.</span><span class="n">0</span><span class="p">.</span><span class="n">msi</span> <span class="p">/</span><span class="n">q</span> <span class="n">DO_NOT_LAUNCH</span><span class="p">=</span><span class="n">True</span>
</code></pre></div>
<p>Aaaand success... now I've got WireGuard and WinTun installed, no user interaction, so far completely silent. Next I gotta create a keypair. There aren't any relevant command-line arguments that I can pass to wireguard.exe, so I went on a hunt for a keypair generator.</p>
<figure align="center">
<img src="https://www.ericlight.com/images/Tech/wireguard_exe_options.png" alt="A list of the few parameters for wireguard.exe - /installmanagerservice, /installtunnelservice, and similar uninstallers. No keygen etc."/>
</figure>
<p>I spent an hour or so scratching around various options to find a keypair generator that looked trustworthy. I honestly couldn't find one... even the one posted on the <a href="https://github.com/WireGuard/WireGuard-tools/tree/master/contrib/keygen-html">WireGuard GitHub</a> includes a caveat from Jason.</p>
<p>Until I decided to have a closer look at the installer source code... the very same code I was looking at when I discovered the DO_NOT_LAUNCH property above.</p>
<div class="highlight"><pre><span></span><code><span class="nt"><Component</span> <span class="na">Directory=</span><span class="s">"System64Folder"</span> <span class="na">Win64=</span><span class="s">"yes"</span> <span class="na">Id=</span><span class="s">"Wg64Executable"</span> <span class="na">Guid=</span><span class="s">"d9b494ec-0959-442c-89ad-6aa175acfd03"</span><span class="nt">></span>
<span class="nt"><File</span> <span class="na">Source=</span><span class="s">"..\$(var.WIREGUARD_PLATFORM)\wg.exe"</span> <span class="na">Id=</span><span class="s">"Wg64Executable"</span> <span class="nt">/></span>
<span class="nt"></Component></span>
</code></pre></div>
<p>So <code>C:\Program Files\WireGuard\WireGuard.exe</code> appears to be just a shell that calls out to <code>C:\Windows\System32\wg.exe</code>. Oh my god that knowledge would have saved me <strong>hours</strong>!!</p>
<p>So... here's how to generate a WireGuard keypair, in Windows, without the GUI. Since system32 is in the path, you can run this from anywhere. The below will create WireGuard.priv and WireGuard.pub in your AppData folder:</p>
<div class="highlight"><pre><span></span><code>PS C:\> wg genkey | tee $ENV:APPDATA\WireGuard.priv | wg pubkey > $ENV:APPDATA\WireGuard.pub
PS C:\> cat $ENV:APPDATA\WireGuard.*
uIGDK+LMDZANniFxrofIpu/hUyezuwCM7qSDVVO+1Gw=
85MxGcWutHJsjFggiZ+J4/vsNYDVEa8zYk53DQZCwyE=
</code></pre></div>
<p><strong><em>AWESOME.</em></strong> Next step is to zoink that into a handy-dandy config file. (More accurately, next step is to delete that private key that I've now posted to the internets)</p>
<p>Right, so it <em>looks</em> like I can't just create a text-based wg0.conf file like I do in Linux. When I do, I get this error:</p>
<div class="highlight"><pre><span></span><code>PS C:\Users> wg setconf wg0 .\wg0.conf
Line unrecognized: ` ■['
Configuration parsing error
</code></pre></div>
<p>I thought this might be the file encoding, so I tried it in ANSI etc, but then I learned that Wireguard for Windows stores it's config files in <code>C:\Windows\System32\config\systemprofile\AppData\Local\WireGuard\Configurations\</code> ... and they're not in plain text. They're stored with the Windows Data Protection API (DPAPI), so perhaps that's what wireguard.exe is expecting?</p>
<p>Either way, I've been playing with this for quite a long time now, so I'm off to take a break for the night or so. Once I figure out how to create a WireGuard config file for an interface I'll post a new article. Hope you enjoyed reading so far!</p>A pork rub for when you've run out of garlic2020-04-26T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2020-04-26:/a-pork-rub-for-when-youve-run-out-of-garlic.html<p>I picked up a set of whole pork loins at Pak 'n Save the other day for like twelve bucks, and being on dinner duty tonight I thought it was time to fire up the smoker. But just last night we'd had a Chicken Tikka Masala which cleaned out our garlic stocks ... what to do?</p>
<p>After a bit of dithering, I made a simple low-garlic rub and it turned out good enough that I'm documenting it here!</p>
<h1>Outta Garlic Pork Rub</h1>
<ul>
<li>1 tbsp salt</li>
<li>2 tbsp brown sugar</li>
<li>1 tbsp …</li></ul><p>I picked up a set of whole pork loins at Pak 'n Save the other day for like twelve bucks, and being on dinner duty tonight I thought it was time to fire up the smoker. But just last night we'd had a Chicken Tikka Masala which cleaned out our garlic stocks ... what to do?</p>
<p>After a bit of dithering, I made a simple low-garlic rub and it turned out good enough that I'm documenting it here!</p>
<h1>Outta Garlic Pork Rub</h1>
<ul>
<li>1 tbsp salt</li>
<li>2 tbsp brown sugar</li>
<li>1 tbsp Cajun seasoning mix (this had garlic in it)</li>
<li>1 tbsp ground cumin</li>
<li>1 tbsp ground coriander</li>
<li>1 tbsp smoked paprika</li>
<li>1/2 tbsp ground ginger</li>
<li>1/2 tbsp chilli flakes</li>
<li>1/2 tbsp turmeric</li>
</ul>
<p>I covered a plate in the rub, then on a different board I sprinkled rub all over the tops of the pork, placed them rub-side-down on the plate-o-rub, and covered the remaining surfaces. I still have probably 2 tbsp of rub left, so I must have used 7 tbsp in total.</p>
<p>Into the fridge for about two hours, and then onto the smoker! I did it over pecan wood until it reached about 60°C, and then boated it in a 50/50 mix of apple juice and ginger beer until it hit an internal temp of 71°C. Then I let it sit for about 30 minutes before we sat down to dinner!</p>
<p>Reflections:</p>
<ul>
<li>I was in a rush this time - no low & slow here. I really want to try it again over much lower heat.</li>
<li>I think it was a bit overcooked... 71°C is a bit hot for pork. Next time I'll pull it off at 65°C and let it sit for a bit longer.</li>
</ul>
<p>Overall, it still got a great score from the rest of the fam (in fact, they're the reason I've recorded this recipe here)!</p>Setting up a Windows Dev VM under ProxmoxVE2020-04-26T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2020-04-26:/setting-up-a-windows-dev-vm-under-proxmoxve.html<p>Righto, I've been using WireGuard for quite a long time now, but I just had my first foray into WireGuard on Windows. I'm trying to roll it into a low-touch VPN deployment sort of thing. </p>
<p>There will be a post about that soon, but this particular post is about <em>setting up the environment</em> for me to play with this stuff... I need a system where I can take snapshots and roll back the drive to a known state. (So I can be sure I'm not missing anything that the installer …</p><p>Righto, I've been using WireGuard for quite a long time now, but I just had my first foray into WireGuard on Windows. I'm trying to roll it into a low-touch VPN deployment sort of thing. </p>
<p>There will be a post about that soon, but this particular post is about <em>setting up the environment</em> for me to play with this stuff... I need a system where I can take snapshots and roll back the drive to a known state. (So I can be sure I'm not missing anything that the installer would do). </p>
<p>I don't have a Windows machine, so I started off by downloading a <a href="https://developer.microsoft.com/en-us/windows/downloads/virtual-machines/">Win10 Dev VM from Microsoft</a>. Since I'm running ProxmoxVE, I chose the VMware image, which will come down as a .zip file.</p>
<p>Download the zip file, and extract it to wherever your VM disk images live (mine is <code>/VM_Local_zpool/</code>)... this will save some time when you're importing the disk. </p>
<p>Next, you simply use the <a href="https://pve.proxmox.com/pve-docs/qm.1.html">importovf</a> function of <code>qm</code> to import the OVF manifest as a new KVM-based VM in Proxmox!</p>
<p><code>~ # qm importovf 103 WinDev2004Eval.ovf VM_Images --format qcow2</code>
<code>Formatting '/VM_Local_zpool/images/103/vm-103-disk-0.qcow2', fmt=qcow2 size=136365211648 cluster_size=65536 preallocation=metadata lazy_refcounts=off refcount_bits=16</code>
<code>(100.00/100%)</code><br>
<code>~ #</code></p>
<p>That was suspiciously easy...</p>
<p>After importing I couldn't launch the VM, but I've seen this error a dozen times and know who to handle it:</p>
<p><code>kvm: -drive file=/VM_Local_zpool/images/103/vm-103-disk-0.qcow2,if=none,id=drive-sata0,format=qcow2,cache=none,aio=native,detect-zeroes=on: file system may not support O_DIRECT</code>
<code>kvm: -drive file=/VM_Local_zpool/images/103/vm-103-disk-0.qcow2,if=none,id=drive-sata0,format=qcow2,cache=none,aio=native,detect-zeroes=on: Could not open '/VM_Local_zpool/images/103/vm-103-disk-0.qcow2': Invalid argument</code>
<code>TASK ERROR: start failed: command '/usr/bin/kvm <-- snip --> -machine 'type=pc'' failed: exit code 1</code></p>
<p>If you're here because you googled the above error, your problem is rooted in this particular bit: <code>file system may not support O_DIRECT</code>. Your problem is that Cache setting on your Hard Disk entry (under VM -> Hardware) is set to "Default (No cache)". Set it to Write Back or Write Through and it'll launch fine.</p>
<p>Okay, so the VM starts with no network card - I went ahead and just added the VMware vmxnet one that Proxmox offers, since that'll already have drivers set up on this VMware image. After that it was a few seconds to join the domain, pop the Computer object into the correct OU, run a gpupdate, and fire up my RDP connection using <a href="https://www.remmina.org">Remmina</a>... and just like that, I've got a Windows machine set up to start playing!</p>
<p>Now that I've shaved that particular set of yaks, I'm ready to start trying to do what I wanted to do earlier this morning. Let's see how tomorrow goes...</p>Using Fail2Ban to insta-block malicious hits2020-04-07T00:00:00+12:002020-04-10T00:00:00+12:00Eric Lighttag:www.ericlight.com,2020-04-07:/using-fail2ban-to-insta-block-malicious-hits.html<p>Okay so a few days ago I <a href="https://www.ericlight.com/moving-to-the-caddy-web-server.html">posted</a> about adopting <a href="https://www.caddyserver.com">Caddy</a>. </p>
<p>Of course, anyone who hosts anything knows that accessible services on the internet will start getting hit by scanners within literal moments of being accessible. On the very first night of having my site live on the new VPS, Logwatch informed me of a bunch of attempts to access wp-admin.php. Sigh.</p>
<p>Well, this entire site is built with my favourite static site generator <a href="https://www.getpelican.com">Pelican</a>. That means I don't have any PHP on my site whatsoever. Why not just …</p><p>Okay so a few days ago I <a href="https://www.ericlight.com/moving-to-the-caddy-web-server.html">posted</a> about adopting <a href="https://www.caddyserver.com">Caddy</a>. </p>
<p>Of course, anyone who hosts anything knows that accessible services on the internet will start getting hit by scanners within literal moments of being accessible. On the very first night of having my site live on the new VPS, Logwatch informed me of a bunch of attempts to access wp-admin.php. Sigh.</p>
<p>Well, this entire site is built with my favourite static site generator <a href="https://www.getpelican.com">Pelican</a>. That means I don't have any PHP on my site whatsoever. Why not just... block anyone that tries to open a PHP page at ericlight.com? <a href="https://www.fail2ban.org">Fail2Ban</a> to the rescue.</p>
<p>Two things we need: A Fail2Ban filter, and a Fail2Ban jail.</p>
<h2>The Filter</h2>
<p><code>nano /etc/fail2ban/filter.d/caddy-php.conf</code> <em>(note, the name of this file must be the same as the identifier in your <code>jail.local</code> file)</em></p>
<div class="highlight"><pre><span></span><code><span class="k">[Definition]</span>
<span class="na">failregex</span> <span class="o">=</span> <span class="s">^<HOST>.*\.php(\s|\?.*)HTTP.*$</span>
<span class="na">ignoreregex</span> <span class="o">=</span>
</code></pre></div>
<p>... that will catch anything in your logs such as:</p>
<div class="highlight"><pre><span></span><code><span class="err">nn.nn.nn.nn - - [07/Apr/2020:23:20:39 +1200] "GET /wp-admin.php HTTP/2.0" 404 0</span>
<span class="err">nn.nn.nn.nn - - [06/Apr/2020:10:12:24 +1200] "GET /index.php?s=index/%5Cthink%5Capp/invokefunction&function=call_user_func_array&vars%5B0%5D=phpinfo&vars%5B1%5D%5B%5D=1 HTTP/1.1" 404 0</span>
<span class="err">nn.nn.nn.nn - - [06/Apr/2020:12:51:31 +1200] "GET /wp-login.php HTTP/1.1" 404 0</span>
</code></pre></div>
<h2>The Jail</h2>
<p><code>nano /etc/fail2ban/jail.local</code></p>
<div class="highlight"><pre><span></span><code><span class="k">[caddy-php]</span>
<span class="na">port</span> <span class="o">=</span> <span class="s">http,https</span>
<span class="na">logpath</span> <span class="o">=</span> <span class="s">/var/log/caddy/access.log</span>
<span class="na">enabled</span> <span class="o">=</span> <span class="s">true</span>
<span class="na">maxretry</span> <span class="o">=</span> <span class="s">1</span>
</code></pre></div>
<p>Note I used <code>maxretry = 1</code> there. This means if an IP triggers that filter <em>a single time</em>, they'll be blocked <strong>immediately</strong>... So you probably don't want to do this just willy-nilly. </p>
<h2>The Result</h2>
<p>With those two parts done (and the obligatory <code>service fail2ban reload</code>, of course), you should find that your web server immediately bans any host that tries to load a .php file from your website!</p>
<div class="highlight"><pre><span></span><code><span class="o">#</span> <span class="n">tail</span> <span class="o">-</span><span class="n">f</span> <span class="o">/</span><span class="n">var</span><span class="o">/</span><span class="n">log</span><span class="o">/</span><span class="n">caddy</span><span class="o">/</span><span class="k">access</span><span class="p">.</span><span class="n">log</span> <span class="o">/</span><span class="n">var</span><span class="o">/</span><span class="n">log</span><span class="o">/</span><span class="n">fail2ban</span><span class="p">.</span><span class="n">log</span>
<span class="o">==></span> <span class="o">/</span><span class="n">var</span><span class="o">/</span><span class="n">log</span><span class="o">/</span><span class="n">caddy</span><span class="o">/</span><span class="k">access</span><span class="p">.</span><span class="n">log</span> <span class="o"><==</span>
<span class="mi">1</span><span class="n">xx</span><span class="p">.</span><span class="mi">1</span><span class="n">xx</span><span class="p">.</span><span class="mi">1</span><span class="n">xx</span><span class="p">.</span><span class="mi">11</span> <span class="o">-</span> <span class="o">-</span> <span class="p">[</span><span class="mi">07</span><span class="o">/</span><span class="n">Apr</span><span class="o">/</span><span class="mi">2020</span><span class="p">:</span><span class="mi">23</span><span class="p">:</span><span class="mi">25</span><span class="p">:</span><span class="mi">55</span> <span class="o">+</span><span class="mi">1200</span><span class="p">]</span> <span class="ss">"GET /arse.php HTTP/1.1"</span> <span class="mi">404</span> <span class="mi">0</span>
<span class="mi">1</span><span class="n">xx</span><span class="p">.</span><span class="mi">1</span><span class="n">xx</span><span class="p">.</span><span class="mi">1</span><span class="n">xx</span><span class="p">.</span><span class="mi">6</span> <span class="o">-</span> <span class="o">-</span> <span class="p">[</span><span class="mi">07</span><span class="o">/</span><span class="n">Apr</span><span class="o">/</span><span class="mi">2020</span><span class="p">:</span><span class="mi">23</span><span class="p">:</span><span class="mi">25</span><span class="p">:</span><span class="mi">57</span> <span class="o">+</span><span class="mi">1200</span><span class="p">]</span> <span class="ss">"GET /arse.php?1234 HTTP/1.1"</span> <span class="mi">404</span> <span class="mi">0</span>
<span class="mi">1</span><span class="n">xx</span><span class="p">.</span><span class="mi">2</span><span class="n">xx</span><span class="p">.</span><span class="mi">6</span><span class="n">x</span><span class="p">.</span><span class="mi">1</span><span class="n">xx</span> <span class="o">-</span> <span class="o">-</span> <span class="p">[</span><span class="mi">07</span><span class="o">/</span><span class="n">Apr</span><span class="o">/</span><span class="mi">2020</span><span class="p">:</span><span class="mi">23</span><span class="p">:</span><span class="mi">26</span><span class="p">:</span><span class="mi">03</span> <span class="o">+</span><span class="mi">1200</span><span class="p">]</span> <span class="ss">"GET /blargh.php HTTP/2.0"</span> <span class="mi">404</span> <span class="mi">0</span>
<span class="o">==></span> <span class="o">/</span><span class="n">var</span><span class="o">/</span><span class="n">log</span><span class="o">/</span><span class="n">fail2ban</span><span class="p">.</span><span class="n">log</span> <span class="o"><==</span>
<span class="mi">2020</span><span class="o">-</span><span class="mi">04</span><span class="o">-</span><span class="mi">07</span> <span class="mi">23</span><span class="p">:</span><span class="mi">25</span><span class="p">:</span><span class="mi">55</span><span class="p">,</span><span class="mi">482</span> <span class="n">fail2ban</span><span class="p">.</span><span class="n">filter</span> <span class="p">[</span><span class="mi">452</span><span class="p">]:</span> <span class="n">INFO</span> <span class="p">[</span><span class="n">caddy</span><span class="o">-</span><span class="n">php</span><span class="p">]</span> <span class="k">Found</span> <span class="mi">1</span><span class="n">xx</span><span class="p">.</span><span class="mi">1</span><span class="n">xx</span><span class="p">.</span><span class="mi">1</span><span class="n">xx</span><span class="p">.</span><span class="mi">11</span> <span class="o">-</span> <span class="mi">2020</span><span class="o">-</span><span class="mi">04</span><span class="o">-</span><span class="mi">07</span> <span class="mi">23</span><span class="p">:</span><span class="mi">25</span><span class="p">:</span><span class="mi">55</span>
<span class="mi">2020</span><span class="o">-</span><span class="mi">04</span><span class="o">-</span><span class="mi">07</span> <span class="mi">23</span><span class="p">:</span><span class="mi">25</span><span class="p">:</span><span class="mi">55</span><span class="p">,</span><span class="mi">551</span> <span class="n">fail2ban</span><span class="p">.</span><span class="n">actions</span> <span class="p">[</span><span class="mi">452</span><span class="p">]:</span> <span class="n">NOTICE</span> <span class="p">[</span><span class="n">caddy</span><span class="o">-</span><span class="n">php</span><span class="p">]</span> <span class="n">Ban</span> <span class="mi">1</span><span class="n">xx</span><span class="p">.</span><span class="mi">1</span><span class="n">xx</span><span class="p">.</span><span class="mi">1</span><span class="n">xx</span><span class="p">.</span><span class="mi">11</span>
<span class="mi">2020</span><span class="o">-</span><span class="mi">04</span><span class="o">-</span><span class="mi">07</span> <span class="mi">23</span><span class="p">:</span><span class="mi">25</span><span class="p">:</span><span class="mi">58</span><span class="p">,</span><span class="mi">309</span> <span class="n">fail2ban</span><span class="p">.</span><span class="n">filter</span> <span class="p">[</span><span class="mi">452</span><span class="p">]:</span> <span class="n">INFO</span> <span class="p">[</span><span class="n">caddy</span><span class="o">-</span><span class="n">php</span><span class="p">]</span> <span class="k">Found</span> <span class="mi">1</span><span class="n">xx</span><span class="p">.</span><span class="mi">1</span><span class="n">xx</span><span class="p">.</span><span class="mi">1</span><span class="n">xx</span><span class="p">.</span><span class="mi">6</span> <span class="o">-</span> <span class="mi">2020</span><span class="o">-</span><span class="mi">04</span><span class="o">-</span><span class="mi">07</span> <span class="mi">23</span><span class="p">:</span><span class="mi">25</span><span class="p">:</span><span class="mi">57</span>
<span class="mi">2020</span><span class="o">-</span><span class="mi">04</span><span class="o">-</span><span class="mi">07</span> <span class="mi">23</span><span class="p">:</span><span class="mi">25</span><span class="p">:</span><span class="mi">58</span><span class="p">,</span><span class="mi">782</span> <span class="n">fail2ban</span><span class="p">.</span><span class="n">actions</span> <span class="p">[</span><span class="mi">452</span><span class="p">]:</span> <span class="n">NOTICE</span> <span class="p">[</span><span class="n">caddy</span><span class="o">-</span><span class="n">php</span><span class="p">]</span> <span class="n">Ban</span> <span class="mi">1</span><span class="n">xx</span><span class="p">.</span><span class="mi">1</span><span class="n">xx</span><span class="p">.</span><span class="mi">1</span><span class="n">xx</span><span class="p">.</span><span class="mi">6</span>
<span class="mi">2020</span><span class="o">-</span><span class="mi">04</span><span class="o">-</span><span class="mi">07</span> <span class="mi">23</span><span class="p">:</span><span class="mi">26</span><span class="p">:</span><span class="mi">03</span><span class="p">,</span><span class="mi">627</span> <span class="n">fail2ban</span><span class="p">.</span><span class="n">filter</span> <span class="p">[</span><span class="mi">452</span><span class="p">]:</span> <span class="n">INFO</span> <span class="p">[</span><span class="n">caddy</span><span class="o">-</span><span class="n">php</span><span class="p">]</span> <span class="k">Found</span> <span class="mi">1</span><span class="n">xx</span><span class="p">.</span><span class="mi">2</span><span class="n">xx</span><span class="p">.</span><span class="mi">6</span><span class="n">x</span><span class="p">.</span><span class="mi">1</span><span class="n">xx</span> <span class="o">-</span> <span class="mi">2020</span><span class="o">-</span><span class="mi">04</span><span class="o">-</span><span class="mi">07</span> <span class="mi">23</span><span class="p">:</span><span class="mi">26</span><span class="p">:</span><span class="mi">03</span>
<span class="mi">2020</span><span class="o">-</span><span class="mi">04</span><span class="o">-</span><span class="mi">07</span> <span class="mi">23</span><span class="p">:</span><span class="mi">26</span><span class="p">:</span><span class="mi">04</span><span class="p">,</span><span class="mi">010</span> <span class="n">fail2ban</span><span class="p">.</span><span class="n">actions</span> <span class="p">[</span><span class="mi">452</span><span class="p">]:</span> <span class="n">NOTICE</span> <span class="p">[</span><span class="n">caddy</span><span class="o">-</span><span class="n">php</span><span class="p">]</span> <span class="n">Ban</span> <span class="mi">1</span><span class="n">xx</span><span class="p">.</span><span class="mi">2</span><span class="n">xx</span><span class="p">.</span><span class="mi">6</span><span class="n">x</span><span class="p">.</span><span class="mi">1</span><span class="n">xx</span>
</code></pre></div>
<p>Great success! You can use the <code>banTime</code> directive to adjust how long these blocks should last for - I've got mine set up to block for an hour.</p>
<h2>Edit 2020-04-10:</h2>
<p>Eh I realised that my RegEx missed these lovely things:</p>
<div class="highlight"><pre><span></span><code><span class="p">[</span><span class="n">ip</span> <span class="n">redacted</span><span class="p">]</span> <span class="o">-</span> <span class="o">-</span> <span class="p">[</span><span class="mi">08</span><span class="o">/</span><span class="n">Apr</span><span class="o">/</span><span class="mi">2020</span><span class="o">:</span><span class="mi">16</span><span class="o">:</span><span class="mi">14</span><span class="o">:</span><span class="mi">10</span> <span class="o">+</span><span class="mi">1200</span><span class="p">]</span> <span class="s">"GET /wp-config.php.new HTTP/1.1"</span> <span class="mi">404</span> <span class="mi">0</span>
<span class="p">[</span><span class="n">ip</span> <span class="n">redacted</span><span class="p">]</span> <span class="o">-</span> <span class="o">-</span> <span class="p">[</span><span class="mi">08</span><span class="o">/</span><span class="n">Apr</span><span class="o">/</span><span class="mi">2020</span><span class="o">:</span><span class="mi">16</span><span class="o">:</span><span class="mi">14</span><span class="o">:</span><span class="mi">14</span> <span class="o">+</span><span class="mi">1200</span><span class="p">]</span> <span class="s">"GET /wp-config.php.old HTTP/1.1"</span> <span class="mi">404</span> <span class="mi">0</span>
<span class="p">[</span><span class="n">ip</span> <span class="n">redacted</span><span class="p">]</span> <span class="o">-</span> <span class="o">-</span> <span class="p">[</span><span class="mi">08</span><span class="o">/</span><span class="n">Apr</span><span class="o">/</span><span class="mi">2020</span><span class="o">:</span><span class="mi">16</span><span class="o">:</span><span class="mi">14</span><span class="o">:</span><span class="mi">17</span> <span class="o">+</span><span class="mi">1200</span><span class="p">]</span> <span class="s">"GET /wp-config.php.bak HTTP/1.1"</span> <span class="mi">404</span> <span class="mi">0</span>
<span class="p">[</span><span class="n">ip</span> <span class="n">redacted</span><span class="p">]</span> <span class="o">-</span> <span class="o">-</span> <span class="p">[</span><span class="mi">08</span><span class="o">/</span><span class="n">Apr</span><span class="o">/</span><span class="mi">2020</span><span class="o">:</span><span class="mi">16</span><span class="o">:</span><span class="mi">14</span><span class="o">:</span><span class="mi">19</span> <span class="o">+</span><span class="mi">1200</span><span class="p">]</span> <span class="s">"GET /wp-config.php.backup HTTP/1.1"</span> <span class="mi">404</span> <span class="mi">0</span>
<span class="p">[</span><span class="n">ip</span> <span class="n">redacted</span><span class="p">]</span> <span class="o">-</span> <span class="o">-</span> <span class="p">[</span><span class="mi">08</span><span class="o">/</span><span class="n">Apr</span><span class="o">/</span><span class="mi">2020</span><span class="o">:</span><span class="mi">16</span><span class="o">:</span><span class="mi">14</span><span class="o">:</span><span class="mi">22</span> <span class="o">+</span><span class="mi">1200</span><span class="p">]</span> <span class="s">"GET /wp-config.php.save HTTP/1.1"</span> <span class="mi">404</span> <span class="mi">0</span>
</code></pre></div>
<p>... so yeah I just changed it to drop anything with <code>.php</code> in the URL. I'll try to remember not to post any articles with .php in the URL lol.</p>
<h2>Credits</h2>
<p>Thanks to Phage and Xyphoid for the help in fine-tuning my rusty RegEx!</p>Moving to the Caddy web server2020-04-05T00:00:00+13:002022-01-05T00:00:00+13:00Eric Lighttag:www.ericlight.com,2020-04-05:/moving-to-the-caddy-web-server.html<p>For the last couple of years I've been running this site, as well as my friend's site (<a href="https://www.undertheumbrella.co.nz">Under The Umbrella</a>) on <a href="https://www.nginx.org">Nginx</a>. Recently my VPS host decided to do away with their cheapest tier, so instead of doubling my annual cost, I hopped onto <a href="https://www.lowendbox.com">https://www.lowendbox.com</a> and found myself a replacement Cheaps McGee VPS to host this.</p>
<p>Well, a major change like that is a great time to learn about something new, so I took the opportunity to get started with <a href="https://www.caddyserver.com">Caddy</a>. If you don't already know about …</p><p>For the last couple of years I've been running this site, as well as my friend's site (<a href="https://www.undertheumbrella.co.nz">Under The Umbrella</a>) on <a href="https://www.nginx.org">Nginx</a>. Recently my VPS host decided to do away with their cheapest tier, so instead of doubling my annual cost, I hopped onto <a href="https://www.lowendbox.com">https://www.lowendbox.com</a> and found myself a replacement Cheaps McGee VPS to host this.</p>
<p>Well, a major change like that is a great time to learn about something new, so I took the opportunity to get started with <a href="https://www.caddyserver.com">Caddy</a>. If you don't already know about Caddy, it's a fast, simple, <em>clean</em> web server. It's written in Go, so it's both fast and memory safe. And hey, it's super simple.</p>
<p>I'm not going to go into a whole lot of detail about setting up Caddy - there are enough tutorials out there already, and really I got all the info I needed from the website. But here are some particularly notable bits:</p>
<h1>The Caddyfile</h1>
<p>This lives in <code>/etc/caddy/Caddyfile</code>:</p>
<div class="highlight"><pre><span></span><code><span class="na">ericlight.com, www.ericlight.com {</span>
<span class="na">file_server</span>
<span class="na">root * /var/www/ericlight.com</span>
<span class="na">import /etc/caddy/caddy_security.conf</span>
<span class="na">log {</span>
<span class="na">output file /var/log/caddy/access.log</span>
<span class="na">format single_field common_log</span>
<span class="na">}</span>
<span class="na">}</span>
<span class="na">undertheumbrella.co.nz, www.undertheumbrella.co.nz {</span>
<span class="na">file_server</span>
<span class="na">root * /var/www/undertheumbrella.co.nz</span>
<span class="na">import /etc/caddy/caddy_security.conf</span>
<span class="na">log {</span>
<span class="na">output file /var/log/caddy/utu_access.log</span>
<span class="na">format single_field common_log</span>
<span class="na">}</span>
<span class="na">}</span>
</code></pre></div>
<p>And, <code>/etc/caddy/caddy_security.conf</code> contains:</p>
<div class="highlight"><pre><span></span><code><span class="na">header {</span>
<span class="na">Strict-Transport-Security "max-age</span><span class="o">=</span><span class="s">31536000; includeSubDomains; preload"</span>
<span class="s"> X-Xss-Protection "1; mode=block"</span>
<span class="s"> X-Content-Type-Options "nosniff"</span>
<span class="s"> X-Frame-Options "DENY"</span>
<span class="s"> Content-Security-Policy "upgrade-insecure-requests"</span>
<span class="s"> Referrer-Policy "strict-origin-when-cross-origin"</span>
<span class="s"> Cache-Control "public, max-age=15, must-revalidate"</span>
<span class="s"> Feature-Policy "accelerometer 'none'; ambient-light-sensor 'none'; autoplay 'self'; camera 'none'; encrypted-media 'none'; fullscreen 'self'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; midi 'none'; payment 'none'; picture-in-picture *; speaker 'none'; sync-xhr 'none'; usb 'none'; vr 'none'"</span>
<span class="na">}</span>
</code></pre></div>
<p><strong> Update 2022-01-05:</strong> Previously I'd used <code>header / {</code> above; that should have been simply <code>header {</code>. Thanks <a href="https://twitter.com/JoHoffmann8">@JoHoffmann8</a> for pointing this out! It's also worth mentioning that Caddy are deprecating the <code>common_log</code> log format, which makes me sad in one way, but I do get it - the Caddy json log file format is far richer, but I liked the easily-ingested syslog format. ¯\_(ツ)_/¯</p>
<hr>
<p>Ok so here's the thing. Caddy really seems to implement Python's ethos of "Batteries Included". The above contents are enough on their own to:</p>
<ol>
<li>Host two separate static websites</li>
<li>Offer two subdomains for each of these websites </li>
<li>Manage the entire certificate creation and renewal process from <a href="https://www.letsencrypt.org">Let's Encrypt</a> for two sites, plus subdomains.</li>
<li>Get an A+ rating on both <a href="https://www.ssllabs.com/ssltest/">SSL Labs</a> and <a href="https://www.securityheaders.io">SecurityHeaders.io</a>(!!)</li>
<li>And, of course, zoink all the logs into separate files under /var/log/caddy</li>
</ol>
<h1>Creating a Caddy Service file</h1>
<p><strong>UPDATE 2020-05-07: With the release of Caddy 2.0, it appears a regular <code>dpkg -i caddy.deb</code> will take care of creating the caddy.service file</strong></p>
<hr>
<p>If you're running Debian, you'll need to create yourself a service file for systemd, so you can get your server to launch Caddy on boot. I got mine from <a href="https://github.com/caddyserver/dist/tree/master/init">https://github.com/caddyserver/dist/tree/master/init</a>:</p>
<p><code>/etc/systemd/system/caddy.service</code>:</p>
<div class="highlight"><pre><span></span><code><span class="c1"># This service file requires the following:</span>
<span class="c1">#</span>
<span class="c1"># 1) Group named caddy:</span>
<span class="c1"># $ groupadd --system caddy</span>
<span class="c1">#</span>
<span class="c1"># 2) User named caddy, with a writeable home folder:</span>
<span class="c1"># $ useradd --system \</span>
<span class="c1"># --gid caddy \</span>
<span class="c1"># --create-home \</span>
<span class="c1"># --home-dir /var/lib/caddy \</span>
<span class="c1"># --shell /usr/sbin/nologin \</span>
<span class="c1"># --comment "Caddy web server" \</span>
<span class="c1"># caddy</span>
<span class="c1">#</span>
<span class="c1"># 3) Caddyfile at /etc/caddy/Caddyfile that is</span>
<span class="c1"># readable by the caddy user</span>
<span class="c1">#</span>
<span class="k">[Unit]</span>
<span class="na">Description</span><span class="o">=</span><span class="s">Caddy Web Server</span>
<span class="na">Documentation</span><span class="o">=</span><span class="s">https://caddyserver.com/docs/</span>
<span class="na">After</span><span class="o">=</span><span class="s">network.target</span>
<span class="k">[Service]</span>
<span class="na">User</span><span class="o">=</span><span class="s">caddy</span>
<span class="na">Group</span><span class="o">=</span><span class="s">caddy</span>
<span class="na">ExecStart</span><span class="o">=</span><span class="s">/usr/bin/caddy run --config /etc/caddy/Caddyfile --environ</span>
<span class="na">ExecReload</span><span class="o">=</span><span class="s">/usr/bin/caddy reload --config /etc/caddy/Caddyfile</span>
<span class="na">TimeoutStopSec</span><span class="o">=</span><span class="s">5s</span>
<span class="na">LimitNOFILE</span><span class="o">=</span><span class="s">1048576</span>
<span class="na">LimitNPROC</span><span class="o">=</span><span class="s">512</span>
<span class="na">PrivateTmp</span><span class="o">=</span><span class="s">true</span>
<span class="na">ProtectSystem</span><span class="o">=</span><span class="s">full</span>
<span class="na">AmbientCapabilities</span><span class="o">=</span><span class="s">CAP_NET_BIND_SERVICE</span>
<span class="k">[Install]</span>
<span class="na">WantedBy</span><span class="o">=</span><span class="s">multi-user.target</span>
</code></pre></div>
<h1>Preventing scans</h1>
<p>Everything above is already pretty secure - Caddy is really good at making security super easy. On top of that, Caddy is the only service hosted on this box, there's no dynamic code (all raw HTML and CSS, thanks to <a href="https://getpelican.com">Pelican</a>), and the only things listening to the internet are SSH and Caddy itself. But even then, I get tired of seeing hundreds of scan reports every day. <a href="https://www.fail2ban.org/">Fail2Ban</a> to the rescue.</p>
<p><code>/etc/fail2ban/filter.d/caddy-4xx.conf</code>:</p>
<div class="highlight"><pre><span></span><code><span class="k">[Definition]</span>
<span class="na">failregex</span> <span class="o">=</span> <span class="s">^<HOST>.*"(GET|POST).*" (404|444|403|400) .*$</span>
<span class="na">ignoreregex</span> <span class="o">=</span>
</code></pre></div>
<p><code>/etc/fail2ban/jail.local</code>:</p>
<div class="highlight"><pre><span></span><code><span class="k">[caddy-4xx]</span>
<span class="na">port</span> <span class="o">=</span> <span class="s">http,https</span>
<span class="na">logpath</span> <span class="o">=</span> <span class="s">/var/log/caddy/access.log</span>
<span class="s"> /var/log/caddy/utu_access.log</span>
<span class="na">enabled</span> <span class="o">=</span> <span class="s">true</span>
<span class="na">banTime</span> <span class="o">=</span> <span class="s">3600</span>
<span class="na">findTime</span> <span class="o">=</span> <span class="s">600</span>
<span class="na">maxretry</span> <span class="o">=</span> <span class="s">5</span>
</code></pre></div>
<h1>Fin!</h1>
<p>And that's all! I had another tweak or two to my Pelican Makefile, to point rsync to the right server, but overall that was an incredibly simple process. The Caddy team have done a spectacular job.</p>Lockdown Chicken2020-03-29T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2020-03-29:/lockdown-chicken.html<p>It's the first weekend of New Zealand's COVID-19 lockdown, and having already been working from home for a week I decided I'd get energetic in the kitchen.</p>
<p>Last night, with some guidance from my mate Nevyn, I put a couple chickens into a brine. I've brined before, but this one was <em>super</em> experimental for me, as usually my brines are just <a href="https://www.allrecipes.com/recipe/170656/simple-chicken-brine/">that one top result</a> on AllRecipes.com, which is about as inspired as plain mayonnaise on pizza.</p>
<p>Well, holy shit I just finished dinner and it was good enough …</p><p>It's the first weekend of New Zealand's COVID-19 lockdown, and having already been working from home for a week I decided I'd get energetic in the kitchen.</p>
<p>Last night, with some guidance from my mate Nevyn, I put a couple chickens into a brine. I've brined before, but this one was <em>super</em> experimental for me, as usually my brines are just <a href="https://www.allrecipes.com/recipe/170656/simple-chicken-brine/">that one top result</a> on AllRecipes.com, which is about as inspired as plain mayonnaise on pizza.</p>
<p>Well, holy shit I just finished dinner and it was good enough that it deserves a blog post. The flavour of the brine <em>just</em> showed through, the post-brine sauces were outstanding, and I did a pumpkin that I'll mention below too!</p>
<hr>
<h2>The Brine</h2>
<p>A brine is mostly there to ensure you get a super-soft and moist chicken at the end of the cook. For this purpose, only water and salt are really necessary. However you can also use the brining time to subtly introduce some flavours!</p>
<ul>
<li>6 litres warm water</li>
<li>½ cup salt</li>
<li>⅓ cup sugar</li>
<li>4 star anise</li>
<li>2 cinnamon quills</li>
<li>12 allspice</li>
<li>10 cloves</li>
<li>About two tsp peppercorns</li>
<li>2 dried Kashmir(?) chillies</li>
</ul>
<p>And, the méthode:</p>
<ol>
<li>Mix your water, salt, and sugar until completely dissolved.</li>
<li>Put the spices into a pan on medium heat, and wiggle them around until the aroma really starts. Make sure you don't singe them!</li>
<li>Add some of your brine to the pan and simmer the spices for five minutes or so, to get that fresh flavour out into the water.</li>
<li>Tip the whole lot back into your pot of brine, making sure you don't leave any flavour behind. It's ready!</li>
<li>Pop your chickens in, and leave them overnight. Weight them down with something if needed, and make sure you turn or mix them a couple times.</li>
</ol>
<figure align="center">
<img src="https://www.ericlight.com/images/Food/brine.jpg" alt="Two chickens in a pot, covered in brine. There are peppercorns, and cinnamon quills floating on top of the water. A star anise and a dried chilli drift languidly." width=300/>
<figcaption><em>Check out that beauty</em></figcaption>
</figure>
<hr>
<h2>The Rub</h2>
<p>One one of the chickens, I used Leena Spices' exquisite <a href="https://leenaspices.co.nz/products/portuguese-seasoning">Portuguese Spice Mix</a> with heaps of crushed garlic and lemon juice. On the other chicken, I decided to make up my own. Here's what I did:</p>
<ul>
<li>1 tsp salt</li>
<li>1 tsp garlic powder</li>
<li>1 tsp smoked paprika</li>
<li>2 tsp sugar</li>
<li>2 tsp Worchestershire sauce</li>
<li>1 Tbsp oil (adjust as desired for thickness)</li>
<li>pinch of cayenne pepper</li>
</ul>
<p>Just add as much oil as you need to thin the mix out enough to spread on your chicken. Also, add enough cayenne pepper for it to actually be fairly hot; it will cool during cooking. I had mine "comfortably warm", but after cooking it was entirely unnoticeable.</p>
<figure align="center">
<img src="https://www.ericlight.com/images/Food/chicken_rub.jpg" alt="A chicken, rubbed with my homemade rub, ready for cooking. It's quite yellow, probably from the paprika." width=300/>
<img src="https://www.ericlight.com/images/Food/leena_chicken.jpg" alt="Another chicken, this time rubbed with Leena Spices' Portuguese spice. It's a bit more red, with visible garlic chunks." width=300/>
<figcaption><em>Left: My spur-of-the-moment rub;   Right: Leena Spices' Portuguese rub </em></figcaption>
</figure>
<hr>
<h2>The Pumpkin</h2>
<p>This was another spur-of-the-moment thing, but it was absolutely a star of the meal. Real basically:</p>
<ol>
<li>Cut your pumpkin in half, along the latitude, to make a couple bowls. (e.g. <strong>not</strong> from stalk to base)</li>
<li>Scoop out the soft inside bits of the pumpkin and discard.</li>
<li>Take a knife and score the inside of the pumpkin bowls with cross-cuts, as deeply as you can manage.</li>
<li>With your finger, just rub about 2 teaspoons of honey around every exposed part of the pumpkin flesh.</li>
<li>Lay some strips of butter around the rim, with an extra pat of butter in the middle.</li>
<li>Into the smoker it goes! I think mine was in for about two hours today.</li>
</ol>
<p>The honey and butter will melt and flow into the cross-cuts you made in the pumpkin, allowing the flavour to penetrate.</p>
<figure align="center">
<img src="https://www.ericlight.com/images/Food/pumpkin_butter.jpg" alt="Pre-cooking pumpkin. Cut in half like a couple bowls, honey rubbed all over, and butter slices arranged around the rim and inside." width=300/>
<img src="https://www.ericlight.com/images/Food/pumpkin_cooking.jpg" alt="The smoker with pumpkins, carrots, and onions. Pumpkins are a rich orange. All the butter has melted and flowed into the bowl." width=300/>
<figcaption><em>Left: Pumpkin about to be introduced to the smoker;   Right: Post-smoker pumpkin... **delicious**</em></figcaption>
</figure>
<hr>
<h2>The End</h2>
<p>Here are the finishing photos! It was really a tremendous meal, and we've got enough left-over to make wraps for everyone tomorrow!</p>
<figure align="center">
<img src="https://www.ericlight.com/images/Food/cooked_chicken.jpg" alt="Post-cooked chicken. It's dark and smokey, still clearly moist. It's difficult to tell the difference, but one has visible garlic chunks." width=300/>
<img src="https://www.ericlight.com/images/Food/cooked_pumpkin.jpg" alt="The pumpkins, along with onions, carrots, and potatoes. All the scoring in the potatoes has opened up and there's still lots of liquid in the pumpkin-bowl." width=300/>
<figcaption><em>Absolutely exquisite. Moist, tender, spicy, complex chicken. Smokey, sweet, soft pumpkin. Sesame carrot, and soft salty potatoes. </em></figcaption>
</figure>Eric's BBQ sauce2020-03-22T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2020-03-22:/erics-bbq-sauce.html<p>Quite a long time ago, I posted my recipe for <a href="https://www.ericlight.com/smokey-bbq-baked-beans.html">smokey BBQ-baked beans</a>. It's still one of the only recipes I've seen which starts with dry beans, and includes slow-cooking in a smoker. Most of the recipes I've found are either for oven baking, or start with a literal can of baked beans (wtf).</p>
<p>Well I'm making baked beans again for the first time in ages, and I've taken the time to write down my tweaks. This is primarily around my BBQ sauce, hence the title of this post!</p>
<p>Just …</p><p>Quite a long time ago, I posted my recipe for <a href="https://www.ericlight.com/smokey-bbq-baked-beans.html">smokey BBQ-baked beans</a>. It's still one of the only recipes I've seen which starts with dry beans, and includes slow-cooking in a smoker. Most of the recipes I've found are either for oven baking, or start with a literal can of baked beans (wtf).</p>
<p>Well I'm making baked beans again for the first time in ages, and I've taken the time to write down my tweaks. This is primarily around my BBQ sauce, hence the title of this post!</p>
<p>Just a few general reminders about baked beans, and then we'll get into it:</p>
<ol>
<li>Soak your beans the night before</li>
<li>Make a barbecue sauce</li>
<li>Simmer your beans for a bit in a normal pot</li>
<li>Add your aromatics and BBQ sauce after the beans are simmering</li>
<li>Cook your beans for a few hours until noms</li>
</ol>
<h1>The BBQ Sauce recipe</h1>
<p>OK here's the sauce:</p>
<ul>
<li>350ml tomato sauce / ketchup / catsup. I used Watties, which is a fairly sweet ketchup with quite low acid </li>
<li>200ml brown sugar - the darker the better. You could substitute in some molasses into white sugar if you need</li>
<li>100ml apple cider vinegar</li>
<li>80ml Worchestershire sauce</li>
</ul>
<p>That's your base sauce. Put them all together in a pot, and bring to a slow simmer while stirring until it's all mixed and smooth.</p>
<p>At this point, you want to start tasting and tweaking it to your tastes. Work out your preferred balance between the zest of the apple cider vinegar, the sweetness of the sugar, and the meaty richness of the Worchestershire sauce.</p>
<p>Once you've got your balance nailed, expand into the flavours:</p>
<ul>
<li>1Tbsp paprika</li>
<li>1Tbsp English mustard</li>
<li>3 drops liquid smoke </li>
<li>1tsp of adobo sauce, if you can find it</li>
<li>alternatively, some cayenne or chilli powder</li>
</ul>
<p>Be careful about your mixing method - take a quarter cup or so of your simmering sauce out, put your tablespoon of paprika into <em>that</em>, mix it up, and <strong>then</strong> add it to your pot. Otherwise you'll get chunks of powder that are a pain to mix in.</p>
<p>Adobo sauce is pretty ... interesting. It turns out, if you have a tin of chipotle peppers, they're almost certainly bathing in adobo sauce. It's also pretty spicy, so you really don't use much, but it adds a whole lot of flavour that is beyond just heat. A teaspoon should be a pretty good starting point though, and you can ramp up from there as needed - it does lose a lot of it's heat while it simmers.</p>
<figure align="center">
<img src="https://www.ericlight.com/images/adobosauce.jpg" alt="A can of chipotle peppers, opened to show them soaking in rich red-brown adobo sauce" width="500"/>
<figcaption><em>Adobo sauce's natural habitat is pretty much a can.</em></figcaption>
</figure>Artsy Moose artisan shaving soap review2020-03-18T00:00:00+13:002020-11-24T21:28:25+13:00Eric Lighttag:www.ericlight.com,2020-03-18:/artsy-moose-artisan-shaving-soap-review.html<p><em>(Reposting from Facebook - originally written 2020-02-19)</em></p>
<p>Tonight I've got something a bit special for my #shavingPost... A few weeks ago, I offered to help beta test a new product - a shave soap in a cup - for Grere Coutie of <a href="https://www.artsymoose.co.nz/">The Artsy Moose</a>.</p>
<p>The Artsy Moose is actually a really groovy little artisan handcraft shop, physically located here in Hamilton, but Grere sells most of her work online as well. Primarily focussed on soaps, there are all sorts on offer - from <a href="https://www.artsymoose.co.nz/shop/product/334634/Activated-Charcoal-Soap/">activated charcoal</a> soap, to <a href="https://www.artsymoose.co.nz/shop/product/344305/Gardeners-Soap-with-Pumice-and-Poppy-Seeds/">gardeners</a> soap, to <em><a href="https://www.artsymoose.co.nz/shop/product/302441/Tuatara-Beer-Soap/">BEER</a></em> soap... even …</p><p><em>(Reposting from Facebook - originally written 2020-02-19)</em></p>
<p>Tonight I've got something a bit special for my #shavingPost... A few weeks ago, I offered to help beta test a new product - a shave soap in a cup - for Grere Coutie of <a href="https://www.artsymoose.co.nz/">The Artsy Moose</a>.</p>
<p>The Artsy Moose is actually a really groovy little artisan handcraft shop, physically located here in Hamilton, but Grere sells most of her work online as well. Primarily focussed on soaps, there are all sorts on offer - from <a href="https://www.artsymoose.co.nz/shop/product/334634/Activated-Charcoal-Soap/">activated charcoal</a> soap, to <a href="https://www.artsymoose.co.nz/shop/product/344305/Gardeners-Soap-with-Pumice-and-Poppy-Seeds/">gardeners</a> soap, to <em><a href="https://www.artsymoose.co.nz/shop/product/302441/Tuatara-Beer-Soap/">BEER</a></em> soap... even <a href="https://www.artsymoose.co.nz/shop/product/299826/Dapper-Dog-Handmade-Soap/">soap for your doggo</a>!</p>
<p>I received the cup yesterday and tonight was my opportunity to take it for a spin!</p>
<p>My setup tonight was my trusty <a href="https://www.razorock.com/?ourproduct=razors">RazoRock</a> Slant, loaded with a Derby Green blade that's a bit worn-in, having just finished it's third shave. I used my synthetic silvertip shaving brush that's been in my rotation for a few years now.</p>
<p>My regular routine for shaving is to hop in the shower, rinse my face, wash and rinse my hair, wash and rinse my face, and then bust out the shaving gear. This way my stubble has some time to soften up while I'm still being nice and efficient.</p>
<p>The first thing I noticed, of course, was the scent! This is a truly enjoyable scent, a bit reminiscent of sandalwood: elegant, woody, and a little musky. It could be a little bit stronger, but I like my scents quite bold, and it certainly isn't weakly scented.</p>
<p>So I gave the soap block a brief rinse in warm water, drained it thoroughly, and got my shaving brush in there. After a few moments I had a beautiful white lather and got to work. I did find the lather to be very short-lived; even though I applied it fairly thickly, by the time I finished one side of my face, the other side had thinned enough that I could see skin. On my second pass I REALLY worked the brush and, although the lather came out thicker, it vanished similarly quickly. </p>
<p><a href="https://time.com/5175901/elizabeth-warren-nevertheless-she-persisted-meaning/">Nevertheless, I persisted</a> <em>(President Warren, 2020 🙌)</em>... The second pass was all good, but by the third pass I was feeling... Quite exposed to my blade. It just felt like I was lacking all the cushioning I'm used to from my regular creams. I didn't let this deter me, and I continued shaving until I achieved my normal closeness of shave. </p>
<p>Folks I gotta say, I was really expecting to have razor burn when I got out of the shower. Persisting with a regular shave while not feeling the cushioning - and with a quickly-diminishing lather, really had me nervous. HOWEVER, I was surprised to find that nothing dire came to pass! I got out of the shower, did my dental hygiene routine, and by then I'm usually feeling a growing burn if my shave was off. But... No burn, no nicks, no cuts. I probably didn't even need aftershave. </p>
<p>But, like, I USED aftershave anyway, of course. <a href="https://theninenine.com/quotes/quote/4241/">I'm not an animal</a>. Interestingly, my aftershave did burn a little today, which is not normal. I don't think it got along well with the shave soap, perhaps. </p>
<p>Overall score for the first round:
Scent, five stars
Cushion, two stars
Lather, two stars
Shave quality, four stars
Face happiness... Actually a full 4.5 stars! </p>
<p>Next shave, I'm going to try my actual badger hair brush, as the lather may have been affected by the synthetic hair. I'll also try a new (corked) blade and a different aftershave, to compare results. I'm also going to get reports from the rest of the family to see how it works with their shaving routines. </p>
<p>And that's not all! I'm sure that Grere will be modifying the recipe in response to this review, and I think it'll only get better as we work through!</p>
<p><strong>[Update 2020-03-18]</strong></p>
<p>I've used this shaving soap quite a few times now! I still find the same - the lather vanishes very quickly, and it still feels very thin... but it still gives actually a superb shave and I've never given myself any nicks or cuts while using it. I haven't managed to convince anyone else to try it, but I'm happy it's in my collection.</p>
<p>I sent this review onto Grere, and as expected, she knew exactly what to tweak:</p>
<p><em>"It sounds like the recipe could do with more stearic acid, this should provide the more stable later and cushioning that you prefer. I will whip up another batch for you to compare at some stage. However, stearic acid is derived from palm oil, which I don't use in my soap - so i'll see if I can try and alternative."</em></p>
<p>So, there you go! I'll be sure to update this post in the future, but for now, this single shave soap is going to last me at least a year. 🙂</p>Where does mass come from?2020-03-18T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2020-03-18:/where-does-mass-come-from.html<p>I’m a bit over halfway through a brilliant set of particle physics lectures by <a href="https://en.wikipedia.org/wiki/Don_Lincoln">Don Lincoln</a>, called <a href="https://www.thegreatcourses.com/courses/the-theory-of-everything-the-quest-to-explain-all-reality.html">The Theory of Everything: The Quest to Explain All Reality</a>. Don has spent many years as an experimental particle physicist, and has worked with particle accelerators at both at Fermilab and at CERN. You may remember him from his co-discovery of the top quark in 1995, or from his membership on the CERN team when they discovered the Higgs boson in 2012. Or heck you might have seen one of his TED …</p><p>I’m a bit over halfway through a brilliant set of particle physics lectures by <a href="https://en.wikipedia.org/wiki/Don_Lincoln">Don Lincoln</a>, called <a href="https://www.thegreatcourses.com/courses/the-theory-of-everything-the-quest-to-explain-all-reality.html">The Theory of Everything: The Quest to Explain All Reality</a>. Don has spent many years as an experimental particle physicist, and has worked with particle accelerators at both at Fermilab and at CERN. You may remember him from his co-discovery of the top quark in 1995, or from his membership on the CERN team when they discovered the Higgs boson in 2012. Or heck you might have seen one of his TED talks. Either way you have this set of lectures, Don Lincoln, and Don’s moustache to thank for today’s episode.</p>
<figure align="center">
<img src="https://www.ericlight.com/images/donlincoln.jpg" alt="A profile photo of Don Lincoln himself, sporting a moustache"/>
<figcaption><em>Thanks, Don's moustache!</em></figcaption>
</figure>
<p>This fascinating (to me) lecture series takes us on a journey through the four known forces of the universe – the strong nuclear force, the weak nuclear force, the electromagnetic force, and the gravitational force. I’ve spent literally hundreds of hours reading on this esoterica (<em>glares pre-emptively at autocorrect</em>), and I know it’s a baffling area, so I’m really just going to skirt around the edges of this. But one particularly outstanding part really got my interest, and I think I can write it in an understandable form here. Wish me luck… ☘️</p>
<p>This post is on the topic of mass. To start looking at this we go down to the foundations of matter – let’s take a quick journey through mass:</p>
<figure align="center">
<img src="https://www.ericlight.com/images/popemass.png" alt="Pope Francis giving mass in front of a large congregation"/>
<figcaption><em>Sorry, wrong door.</em></figcaption>
</figure>
<h2>What are things?</h2>
<p>To get us started, I’ve put the below into a bulleted list – every level is the next step down in matter:</p>
<ul>
<li>
<p>You, a standard human being, are made up of <strong>molecules</strong> (mostly water), along with a collection of bad ideas and faulty memories. I’m not judging.</p>
<ul>
<li>
<p>Those molecules in your body are made up of <strong>atoms</strong> – mostly carbon, hydrogen, and oxygen.<br>
Let’s look closer at <strong>hydrogen</strong>. <em>*squints*</em></p>
<ul>
<li>
<p>A <strong>hydrogen atom</strong> is the simplest atom. It has the atomic number of 1, meaning its nucleus has only a single <strong>proton</strong>, which is balanced by a single <strong>electron</strong>.</p>
<p><em>Side-note: Hydrogen is a little special because it doesn’t have a neutron in its nucleus. In contrast, heavy hydrogen – known as deuterium – has a proton, an electron, and a neutron.</em></p>
<ul>
<li>
<p>A proton is, in turn, made up of three <strong>quarks</strong>, and weighs roughly 938 MeV/<em>c</em><sup>2</sup>. (that’s megaelectronvolts… more below)</p>
<ul>
<li>
<p>An <strong>up quark</strong> (carrying a positive electric charge of “plus two-thirds”) has a mass of roughly 2.3 MeV/<em>c</em><sup>2</sup> (ignore that part)</p>
</li>
<li>
<p>The <strong>down quark</strong> (carrying a negative electric charge of “minus one-third”) has a mass of roughly 4.8 MeV/<em>c</em><sup>2</sup> (ignore that too, the fun bit is coming)</p>
<ul>
<li>
<p><em>(Quarks appear to be made up of <strong>strings</strong>, but that’s too deep for this article. Extra credit: String theory, superstring theory, and M theory)</em></p>
</li>
<li>
<p>Holding the quarks together are the <strong>Gluons</strong>, which are the particles which mediate the strong nuclear force. These are massless<em>-ish</em>, coming in at <em>almost</em> exactly 0 MeV/<em>c</em><sup>2</sup>.</p>
</li>
</ul>
</li>
<li>
<p>A proton is made of <strong>two up quarks and a down quark</strong>, which gives it a total electric charge of +1. (four-thirds from the up quarks, minus a third from down quark)</p>
</li>
</ul>
</li>
<li>
<p>The <strong>electron</strong> is not made up of quarks – it appears to be a primary particle (specifically, a <em>lepton</em>) that cannot be subdivided. It has an electric charge of -1, and a mass of about 0.5 MeV/<em>c</em><sup>2</sup>.</p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2>What’s a MeV, and has it been approved by the FDA?</h2>
<p>Okay, so you’ve probably never seen mass described in MeV/<em>c</em><sup>2</sup> before. That’s because people live in the world of Relatively Big Things™, so we generally think of mass as what you might measure on a set of bathroom scales (also known as m’ass). But when you’re looking at particle physics, things get <strong><em>way</em></strong> fuzzier... SO fuzzy, in fact, that we don’t weigh things in grams – we weigh them in energy! Specifically, in electron-volts. </p>
<p>For example, a proton weighs 938 million electron-volts (/<em>c</em><sup>2</sup>), and an electron weighs about 500,000 electron-volts. CBut… how does *that* work? How on earth do we measure mass in energy? You wouldn’t say "this glass weighs 500 calories", would you?</p>
<figure align="center">
<img src="https://www.ericlight.com/images/frysquint.png" alt="Fry, from the animation Futurama, squinting in deep suspicion"/>
<figcaption><big><strong><em>...WOULD YOU?</em></strong></big></figcaption>
</figure>
<p>HECK YEAH, you would! It’s the formula most deeply burned into your brain from high school: <em>E=mc<sup>2</sup></em>. Energy (in joules) = Mass (in kilograms) * the speed of light (in metres per second) squared. Einstein’s been saying it for over a hundred years… mass is energy, and energy is mass! And mass contains a <em><strong>whole honkin' bunch</strong></em> of energy. So much energy that a single gram of matter – about the mass of a business card – looks something like this:</p>
<div class="highlight"><pre><span></span><code>Energy (joules) = 1 gram * speed of light^2
Energy (joules) = 0.001 * 300000000 * 300000000
Energy of 1 gram of matter = 9,000,000,000,000,000 joules
</code></pre></div>
<p>... or about 2,151,051,625,239 calories.</p>
<figure align="center">
<img src="https://www.ericlight.com/images/wowmass.png" alt="A photo of someone holding a business card. The business card simply reads 'Wow', in quotation marks, with a picture of Owen Wilson. It is very droll."/>
<figcaption><em>That’s a lot of calories for a piece of cardboard. Probably better off eating pizza.</em></figcaption>
</figure>
<p>So yep, you can definitely weigh things in energy ... and because subatomic particles are so small, energy is a totally sensible measure to use. So let’s get back to the world of the extra-tiny.</p>
<h2>Those numbers look fishy...</h2>
<p>Yes, those numbers are weird. And I’m not talking about my equations above, I’m talking about the mass of an atom. Check it out again:</p>
<p><em>Proton = 2x up quarks + 1x down quark = 938 MeV/c<sup>2</sup></em></p>
<p>But the two up quarks only bring 4.6 MeV/<em>c</em><sup>2</sup> to the party, and that down quark is only 4.8 MeV/<em>c</em><sup>2</sup>, adding up to a mere 9.4 MeV/<em>c</em><sup>2</sup>. In fact, when you put together the mass of all the components of a proton, you still only see about 2% of the mass of the proton. So… where’s all that other mass coming from?</p>
<p>Well, okay. Those quarks aren’t just sitting stationary – they’re moving around at nearly the speed of light, within an incredibly tiny area. In fact, these quarks are fizzing around in an area approximately one-quadrillionth of a meter.</p>
<p>And here’s the whole idea that got me writing this post:</p>
<p>Our quarks, zooming around near the speed of light, and confined within such an incredibly tiny area… Well heck, that’s a whole lot of energy.</p>
<p>And what is energy? </p>
<p><big><em>It's <strong>mass</strong></em></big>.</p>
<p>And <strong>that</strong> is where most of the mass of an atom comes from. From this <em>kinetic</em> energy, found within in the quantum foam, and expressing itself in our universe as mass.</p>
<figure align="center">
<img src="https://www.ericlight.com/images/protoninnards.jpg" alt="An artist's depection of three quarks, swirling around in an energy field, and held together by gluons -- forming a proton"/>
<figcaption><em>Big or small, the universe is full of astounding beauty.</em></figcaption>
</figure>
<p><em>fin.</em></p>Fail2Ban+Nginx (blocking repeated 404's, etc)2020-03-16T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2020-03-16:/fail2bannginx-blocking-repeated-404s-etc.html<p>After hosting a <a href="https://www.iredmail.org">mail server</a> for a few years, I've gotten tired of seeing alllll the 404 attempts in my daily logwatch. Fail2Ban can help here really well, and it turns out to be really easy.</p>
<p>Start with <code>nano /etc/fail2ban/filter.d/nginx-4xx.conf</code> (I'm counting on your running Debian and having things in default locations here), and enter the following:</p>
<div class="highlight"><pre><span></span><code><span class="k">[Definition]</span>
<span class="na">failregex</span> <span class="o">=</span> <span class="s">^<HOST>.*"(GET|POST).*" (404|444|403|400) .*$</span>
<span class="na">ignoreregex</span> <span class="o">=</span>
</code></pre></div>
<p><em>Note: Make sure you use a capital 'D' in Definition there.</em></p>
<p>Now, edit your /etc/fail2ban/jail.conf …</p><p>After hosting a <a href="https://www.iredmail.org">mail server</a> for a few years, I've gotten tired of seeing alllll the 404 attempts in my daily logwatch. Fail2Ban can help here really well, and it turns out to be really easy.</p>
<p>Start with <code>nano /etc/fail2ban/filter.d/nginx-4xx.conf</code> (I'm counting on your running Debian and having things in default locations here), and enter the following:</p>
<div class="highlight"><pre><span></span><code><span class="k">[Definition]</span>
<span class="na">failregex</span> <span class="o">=</span> <span class="s">^<HOST>.*"(GET|POST).*" (404|444|403|400) .*$</span>
<span class="na">ignoreregex</span> <span class="o">=</span>
</code></pre></div>
<p><em>Note: Make sure you use a capital 'D' in Definition there.</em></p>
<p>Now, edit your /etc/fail2ban/jail.conf, and add these lines:</p>
<div class="highlight"><pre><span></span><code><span class="k">[nginx-4xx]</span>
<span class="na">enabled</span> <span class="o">=</span> <span class="s">true</span>
<span class="na">port</span> <span class="o">=</span> <span class="s">http,https</span>
<span class="na">logpath</span> <span class="o">=</span> <span class="s">/var/log/nginx/access.log</span>
<span class="na">maxretry</span> <span class="o">=</span> <span class="s">3</span>
</code></pre></div>
<p>Of course, modify your maxretry as desired. Refresh your Fail2Ban rules with <code>service fail2ban restart</code>, and it should now be on the lookout for repeated 4xx errors.</p>
<p>You can confirm it's working with: <code>fail2ban-client status nginx-4xx</code>:</p>
<div class="highlight"><pre><span></span><code>Status for the jail: nginx-4xx
|- Filter
| |- Currently failed: 2
| |- Total failed: 9
| `- File list: /var/log/nginx/access.log
`- Actions
|- Currently banned: 2
|- Total banned: 2
`- Banned IP list: 123.232.123.101 123.232.123.102
</code></pre></div>
<p><em>Success!</em></p>
<p>Worth mentioning... for the first while I thought it wasn't working, but I realised I was trying to trigger the rule from on the same LAN, and ...</p>
<div class="highlight"><pre><span></span><code><span class="k">[DEFAULT]</span>
<span class="c1"># time is in seconds. 3600 = 1 hour, 86400 = 24 hours (1 day)</span>
<span class="na">findtime</span> <span class="o">=</span> <span class="s">3600</span>
<span class="na">bantime</span> <span class="o">=</span> <span class="s">3600</span>
<span class="na">maxretry</span> <span class="o">=</span> <span class="s">5</span>
<span class="na">ignoreip</span> <span class="o">=</span> <span class="s">127.0.0.1 127.0.0.0/8 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16</span>
</code></pre></div>
<p>... I was hitting it from within the ignoreip range. 😬</p>
<p>And of course, I can't finish off a blog without giving credit where it's due. I got this all from GitHub user AysadKozanoglu, here: <a href="https://gist.github.com/AysadKozanoglu/1335735272fb3b00a03bd3eea22af818">https://gist.github.com/AysadKozanoglu/1335735272fb3b00a03bd3eea22af818</a></p>sa-compile failing during upgrade2020-03-15T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2020-03-15:/sa-compile-failing-during-upgrade.html<p>I just spent an hour troubleshooting the most ridiculous thing. I guess to help people search, I'd describe this as "dpkg failing at sa-compile in Debian 10" but that's really not a good picture of what's happening here...</p>
<div class="highlight"><pre><span></span><code>Setting up sa-compile <span class="o">(</span><span class="m">3</span>.4.2-1~deb9u3<span class="o">)</span> ...
Running sa-compile <span class="o">(</span>may take a long <span class="nb">time</span><span class="o">)</span>
/bin/sh: <span class="m">1</span>: x86_64-linux-gnu-gcc: Permission denied
make: *** <span class="o">[</span>body_0.o<span class="o">]</span> Error <span class="m">126</span>
<span class="nb">command</span> <span class="s1">'make PREFIX=/tmp/.spamassassin22062Ifq5yDtmp/ignored INSTALLSITEARCH=/var/lib/spamassassin/compiled/5.024/3.004002 >>/tmp/.spamassassin22062Ifq5yDtmp/log'</span> failed: <span class="nb">exit</span> <span class="m">2</span>
dpkg: error processing package sa-compile <span class="o">(</span>--configure …</code></pre></div><p>I just spent an hour troubleshooting the most ridiculous thing. I guess to help people search, I'd describe this as "dpkg failing at sa-compile in Debian 10" but that's really not a good picture of what's happening here...</p>
<div class="highlight"><pre><span></span><code>Setting up sa-compile <span class="o">(</span><span class="m">3</span>.4.2-1~deb9u3<span class="o">)</span> ...
Running sa-compile <span class="o">(</span>may take a long <span class="nb">time</span><span class="o">)</span>
/bin/sh: <span class="m">1</span>: x86_64-linux-gnu-gcc: Permission denied
make: *** <span class="o">[</span>body_0.o<span class="o">]</span> Error <span class="m">126</span>
<span class="nb">command</span> <span class="s1">'make PREFIX=/tmp/.spamassassin22062Ifq5yDtmp/ignored INSTALLSITEARCH=/var/lib/spamassassin/compiled/5.024/3.004002 >>/tmp/.spamassassin22062Ifq5yDtmp/log'</span> failed: <span class="nb">exit</span> <span class="m">2</span>
dpkg: error processing package sa-compile <span class="o">(</span>--configure<span class="o">)</span>:
subprocess installed post-installation script returned error <span class="nb">exit</span> status <span class="m">25</span>
<-- snip -->
Errors were encountered <span class="k">while</span> processing:
sa-compile
E: Sub-process /usr/bin/dpkg returned an error code <span class="o">(</span><span class="m">1</span><span class="o">)</span>
</code></pre></div>
<p>In my defence, it seemed similar to a recurring issue I've had on this server in the past, (which I now promise to address in a separate post). That's why I ended up on a red herring hunt.</p>
<p>Anyway, I spent a bunch of time trying to troubleshoot dpkg and Python, before realising that a few months ago I'd installed <a href="https://cisofy.com/lynis">Lynis</a> and worked through a bunch of the hardening recommendations.</p>
<p>... One of which is restricting the execute permissions on /usr/bin/gcc. Which is a symlink to /usr/bin/gcc-6. Which is a symlink to x86_64-linux-gnu-gcc-6.</p>
<div class="highlight"><pre><span></span><code>root@x:/usr/bin# ls -l x86_64-linux-gnu-gcc-6
-rw-r--r-- <span class="m">1</span> root root <span class="m">949016</span> Feb <span class="m">15</span> <span class="m">2018</span> x86_64-linux-gnu-gcc-6
</code></pre></div>
<p>Yes. I was experiencing problems compiling things because I'd removed execute permissions for all users on the compiler I needed, and I'd spent an hour ignoring the "Permission denied" error that told me where to look.</p>
<p>Fixed with a simple <code>chmod 744 /usr/bin/x86_64-linux-gnu-gcc-6</code>.</p>FreeNAS finally supports ECC crypto!2020-02-02T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2020-02-02:/freenas-finally-supports-ecc-crypto.html<p>Woo! <a href="https://www.freenas.org">FreeNAS</a> finally supports ECC crypto for it's SSL certificates in 11.3!</p>
<p>I <a href="https://redmine.ixsystems.com/issues/27665">reported this as a bug</a> almost exactly two years ago, and kept having to do nasty workarounds to make it work every time I installed an update. Very happy that it's finally sorted and I can use my proper shiny elliptic curve SSL setup! :)</p>Fortinet SSL VPN Certificate extensions2020-01-19T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2020-01-19:/fortinet-ssl-vpn-certificate-extensions.html<p>If you're setting up a new SSL VPN with certificate authentication, and if you already have an internal PKI, you're probably considering using your internal certification authority to create the SSL keys and certificates for your VPN clients. Awesome! This is a great and easy way to do this job.</p>
<p>But there's a dearth of information on the Interwebs regarding what Extended Key Usages you need to have enabled in your Certificate Template for these. There are a heap available, including Email Signing, Timestamping, Code Signing, IPSec SSL things (about …</p><p>If you're setting up a new SSL VPN with certificate authentication, and if you already have an internal PKI, you're probably considering using your internal certification authority to create the SSL keys and certificates for your VPN clients. Awesome! This is a great and easy way to do this job.</p>
<p>But there's a dearth of information on the Interwebs regarding what Extended Key Usages you need to have enabled in your Certificate Template for these. There are a heap available, including Email Signing, Timestamping, Code Signing, IPSec SSL things (about 8 of these), and way more options.</p>
<p>Well, your search can end now. There's only one Extended Key Usage option required for SSL certificate authentication with the Fortinet FortiClient VPN:</p>
<p><strong><em>Client Authentication</em></strong></p>
<p>That's it. That's the post.</p>What's so weird about lightspeed, anyway?2020-01-16T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2020-01-16:/whats-so-weird-about-lightspeed-anyway.html<p>Have you ever experienced that thing where you're in your car, stopped at a traffic light - you suddenly get the sensation that you're rolling backward, so you slam on your brake... but you already had your brake on, and you weren't moving! It was the car beside you rolling <em>forward</em>, but your brain misinterpreted it as your own - backwards - motion.</p>
<p>So, another mental image: imagine that you find yourself suddenly transported to a quiet, peaceful mountaintop. There's a monastery here, and Monks are quietly meditating. There is no sound, no …</p><p>Have you ever experienced that thing where you're in your car, stopped at a traffic light - you suddenly get the sensation that you're rolling backward, so you slam on your brake... but you already had your brake on, and you weren't moving! It was the car beside you rolling <em>forward</em>, but your brain misinterpreted it as your own - backwards - motion.</p>
<p>So, another mental image: imagine that you find yourself suddenly transported to a quiet, peaceful mountaintop. There's a monastery here, and Monks are quietly meditating. There is no sound, no wind, just silence and calm. You would probably say you're standing perfectly still.</p>
<p>Now, remembering that perception of stillness, think about the example in <a href="https://twitter.com/KevinPaulGregg/status/1213614627583455233">this tweet</a>:</p>
<blockquote>
<p>Take a kid & explain to him the true fact that the Sun is so far away that it would take a car going 100 mph a 100 years non-stop to get there. And then tell him to picture that same distance BEYOND the Sun! And then tell him that he and you were at that very spot 6 months ago. </p>
<p>-- @KevinPaulGregg</p>
</blockquote>
<p>... your peaceful mountaintop really wasn't that still <em>at all</em>. In fact, it was hurtling through the galaxy at ... (<em>cough</em>) ... an astronomical rate. And on top of that, it's spinning wildly: at the equator, the earth's surface is moving at almost 1700km/h. </p>
<p>This speaks to the very basis of an important question: <em>What __is__ speed?</em></p>
<p>Over 400 years ago, Galileo Galilei's Principle of Relativity (not to be confused with Einstein's Theory of Relativity) emphasised that the concept of speed <strong>requires</strong> a frame of reference. That is, speed is <em>always</em> relative to something else. If you're driving at 100km/h, that speed is relative to the road under your tyres - but compared to a motorbike passing you at 120km/hr, you're moving <em>backwards</em>. Or ... from a different perspective, you're sitting still, and the motorbike is only travelling at 20km/hr. And no matter how fast you're driving, your steering wheel isn't really moving relative to you.</p>
<p>OK I think I've explained that point to death now. Speed is always measured between <strong>two</strong> points in space. But here's the interesting bit.</p>
<p><a href="https://en.wikipedia.org/wiki/Maxwell%27s_equations">Maxwell's Equations</a>, published in the 1860's, can be used to calculate the speed of light - exactly 299,793,458 metres per second in a vacuum. But there's something missing: that all-important frame of reference; the OTHER point in space to measure the speed against. What's going on there? Lots of theories and experiments were floated to figure out where this missing factor was, but everything was shown to be incorrect... that is, until Einstein looked at the problem.</p>
<p>Einstein - in typical Einstein fashion - simply looked and said, "if the speed of light doesn't have a frame of reference, that must mean that the speed of light is the same in <strong>any</strong> frame of reference". That is, if you shine a torch forward, the light is travelling away from you at 300,000km/s. If you keep the torch on and hop into a speeding car, the light is <em>still</em> travelling away from you at 300,000km/s. If you turn around and point the torch out the rear window, the light is travelling away from you at 300,000km/s... and towards someone else, <em>still</em> at 300,000km/s. So <em>what's happened to the speed of your car??</em></p>
<p>Okay, so the speed of light is weird. But the <strong>weirdest</strong> part is what happens when you look at what that means. Let's go back to my earlier question -- <em>what is speed</em>? In one way, this is easy: speed is simply the distance travelled over a certain duration. But take a closer look at what those words mean: distance refers to space; duration refers to time. So, speed is the rate of movement through spacetime. Fine, semantics, whatever. </p>
<p>But these semantics matter. Because what we're seeing here isn't just <em>light</em> being weird: now we're actually seeing <strong>space and time</strong> moving weirdly - dancing around themselves in a big conspiracy to force the speed of light to be 300,000km/s, no matter what your frame of reference is.</p>
<p>It's time to wrap up this episode - mostly because I've reached the limits of my knowledge. Earlier in this article, I asked "what's happened to the speed of your car" and, frankly, I have no idea. When it comes to the warping of spacetime I get really confused. If you're travelling in a train at 200,000km/s, and point a powerful laser in the direction of travel, that laser's light is going 300,000km/s relative to you. But ... then we get silly business, like Lorentz contraction squishing the length in the direction of travel, time dilation starts messing with things, and we get space bending. So to the outside observer, the laser is going ... 300,000km/s. ¯\_(ツ)_/¯</p>
<blockquote>
<p>"People assume that time is a strict progression of cause to effect, but actually — from a non-linear, non-subjective viewpoint — it's more like a big ball of wibbly-wobbly... timey-wimey... stuff." </p>
<p>-- The Tenth Doctor, Doctor Who, "Blink"</p>
</blockquote>The tension between classical and relativistic mechanics2020-01-09T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2020-01-09:/the-tension-between-classical-and-relativistic-mechanics.html<p>When I was considering writing my post on time dilation, I expected precisely zero feedback... just on the basis that nobody would read it. I'm really pleased with the feedback I actually got, and you've all spurred me to write another post on the topic. So today, I'm going to give you a brief glimpse into what caused all this ruckus: Einstein's general theory of relativity.</p>
<p>If you remember, Einstein first came up with the special theory of relativity in 1905, and it took another ten years to get to …</p><p>When I was considering writing my post on time dilation, I expected precisely zero feedback... just on the basis that nobody would read it. I'm really pleased with the feedback I actually got, and you've all spurred me to write another post on the topic. So today, I'm going to give you a brief glimpse into what caused all this ruckus: Einstein's general theory of relativity.</p>
<p>If you remember, Einstein first came up with the special theory of relativity in 1905, and it took another ten years to get to the general theory of relativity. This alone should show you that the jump from the special theory to the general theory was a major leap - but let's step back and see what this is all about.</p>
<p>Our very good childhood friend, Isaac Newton, published his <em>Prinicpia</em> in <strong>SIXTEEN EIGHTY SEVEN</strong>, which is... like... aaaaages ago. With this, he laid the foundation of "classical mechanics", which are the physical concepts and mathematical methods that describe the motion of objects under a variety of forces.</p>
<p>Classical mechanics worked well - <em>really</em> well. There were tweaks here and there there over the ~<em>centuries</em>~, but overall, classical (or "Newtonian") physics had things pretty much nailed... That is, until we started thinking about things that were really heavy, really small, or really fast... at that point, classical mechanics started to fray at the edges. </p>
<p>One of the earliest recognised failures of classical mechanics was the "precession of the perihelion of Mercury". Don't worry what those words mean; basically, Mercury's orbit didn't behave quite the way that classical mechanics said it should. The effect is suuuuper tiny: classical mechanics says that Mercury's orbit should change by 5557 arcseconds per century, but in reality it changes by 5600 arcseconds per century... a difference of 43 arcseconds.</p>
<p>How big is 43 arcseconds? It's about two-thirds of one degree. If you stand on a flat field and imagine a soccer ball on the ground, a kilometer away, the angle drawn from the ground under your feet to the top of that soccer ball is bigger than the 43 arcsecond discrepancy. </p>
<p>... I'm gonna say that again in case you missed it: that was <strong>per century</strong>. Less than a kilometre-away-soccer-ball every hundred years. Yikes.</p>
<p>Where did this discrepancy come from? It all started from a very fair assumpiton of Isaac Newton's: he perched his calculations on the basis that things were consistent. Well, the universe Does Not Roll That Way™. Space warps; time stretches; light falls into gravity wells. But because these effects aren't really visible in our day-to-day life, it took almost two hundred years - and the genius of Einstein - before classical mechanics was overturned by the general theory of relativity in 1915.</p>
<p>Okay this has become a little long and rambling now, so I'm going to take a break and come back to the topic next week! :)</p>Zentyal 6.0 to 6.1 upgrade getting stuck2019-12-17T00:00:00+13:002020-12-06T21:42:37+13:00Eric Lighttag:www.ericlight.com,2019-12-17:/zentyal-60-to-61-upgrade-getting-stuck.html<p>So I faced a little challenge with a <a href="https://www.zentyal.com">Zentyal</a> server the other day. I was upgrading from ye olde 6.0 to 6.1, when everything just stopped. I let it sit in the corner for about an hour or so, but it never picked up the thread. All the services were still live, so I logged in to have a look.</p>
<p>(Note, my DNS server is named RIMU; yours may be something else!)</p>
<p>Running <code>ps aux</code>, I discovered this line:</p>
<div class="highlight"><pre><span></span><code>sh -c /usr/bin/sudo -p sudo: /var/lib …</code></pre></div><p>So I faced a little challenge with a <a href="https://www.zentyal.com">Zentyal</a> server the other day. I was upgrading from ye olde 6.0 to 6.1, when everything just stopped. I let it sit in the corner for about an hour or so, but it never picked up the thread. All the services were still live, so I logged in to have a look.</p>
<p>(Note, my DNS server is named RIMU; yours may be something else!)</p>
<p>Running <code>ps aux</code>, I discovered this line:</p>
<div class="highlight"><pre><span></span><code>sh -c /usr/bin/sudo -p sudo: /var/lib/zentyal/tmp/x2M7gkZVvm.cmd <span class="m">2</span>> /var/lib/zentyal/tmp/stderr
</code></pre></div>
<p>So, I had a quick look at the contents of that stderr file:</p>
<div class="highlight"><pre><span></span><code><span class="c1"># cat /var/lib/zentyal/tmp/stderr </span>
Password has expired
dns-RIMU@ad.ericlight.com<span class="err">'</span>s Password:
</code></pre></div>
<p>And what does that temp .cmd file contain?</p>
<div class="highlight"><pre><span></span><code><span class="c1"># cat /var/lib/zentyal/tmp/x2M7gkZVvm.cmd </span>
kinit -k -t /var/lib/samba/private/dns.keytab dns-RIMU
</code></pre></div>
<p>Running that kinit command indeed prompts for a password reset, but the interesting thing is that samba-tool shows me this password shouldn't expire:</p>
<div class="highlight"><pre><span></span><code><span class="c1"># pdbedit -u dns-RIMU -v | grep change</span>
Password can change: Wed, <span class="m">31</span> Oct <span class="m">2018</span> <span class="m">21</span>:47:30 NZDT
Password must change: never
</code></pre></div>
<p>... <em>riiiiiiight</em>, that's a bit interesting. And yet I'm still being prompted to set a new password. I used samba-tool to remind samba that this password shouldn't expire:</p>
<div class="highlight"><pre><span></span><code><span class="c1"># samba-tool user setexpiry dns-RIMU --noexpiry</span>
Expiry <span class="k">for</span> user <span class="s1">'dns-RIMU'</span> disabled.
</code></pre></div>
<p>And now...</p>
<div class="highlight"><pre><span></span><code><span class="c1"># pdbedit -u dns-RIMU -v | grep -i change</span>
Password can change: Wed, <span class="m">31</span> Oct <span class="m">2018</span> <span class="m">21</span>:47:30 NZDT
Password must change: Tue, <span class="m">19</span> Jan <span class="m">2038</span> <span class="m">16</span>:14:07 NZDT
</code></pre></div>
<p>Now I can run kinit against dns-RIMU perfectly fine, and indeed the Zentyal upgrade succeeded!</p>StarCraft Remastered broken under Wine2019-12-09T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2019-12-09:/starcraft-remastered-broken-under-wine.html<p>I know this post is only going to be relevant for a couple of weeks, but today I tried to launch StarCraft Remastered under WINE and it crashed.</p>
<p>Pertinent info:
StarCraft Version 1.23.2.6926
WINE version 4.20-staging
Battle.Net version 1.18.0.11698</p>
<p>Fix was to open the Battle.Net settings -> Game Settings -> "Launch 32-bit client (instead of 64-bit)"</p>
<p>Apparently the 64-bit version has become the default sometime since I last played it (October?!): https://us.forums.blizzard.com/en/starcraft/t/enabling-64-bit/458/7</p>Spacetime, and Time Dilation2019-11-10T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2019-11-10:/spacetime-and-time-dilation.html<p>I remember reading Stephen Hawking's <em>A Brief History of Time</em> back when I was about 16 years old - a bit over 20 years ago. I didn't even come close to understanding it then. I re-read it on Audible a year ago and I can report that I still didn't understand it at all. Either way, I've been interested in physics and spacetime for a huge chunk of my life, and I wish I'd spent more time on mathematics when I was younger, because I'd have really loved to be a …</p><p>I remember reading Stephen Hawking's <em>A Brief History of Time</em> back when I was about 16 years old - a bit over 20 years ago. I didn't even come close to understanding it then. I re-read it on Audible a year ago and I can report that I still didn't understand it at all. Either way, I've been interested in physics and spacetime for a huge chunk of my life, and I wish I'd spent more time on mathematics when I was younger, because I'd have really loved to be a theoretical physicist. I shit you not. The universe just seems to be more predictable than computers.</p>
<p>Einstein published the special theory of relativity in 1905, and it took him another ten years to bring this into the general theory of relativity (which incorporated gravity) in 1915. The special theory is only "special" in the sense that it assumes a flat spacetime; it was the <strong>general</strong> theory which extended relativity to allow for the curvature of spacetime - for example, the curvature caused by massive objects.</p>
<p>Today I'm going to share my understanding of time dilation, based on what I've learned from Dr Brian Greene, Dr Michio Kaku, and my favourite astrophysicist Marcus Chown. I'll start with a disclaimer: I don't understand any of the calculations behind any of this. I'm familiar with some of the <em>words</em>, and I have a vague grasp of some of the concepts, but I'm mostly limited to regurgitating things I've read and then swearing loudly to distract people from asking questions. </p>
<p>I'm also quite conscious that this is around step three in the age-old progression:</p>
<blockquote>
<p><em>Primary school</em>: "This is how the weather works."<br>
<em>High school</em>: "That wasn't quite right - <em>this</em> is how the weather works."<br>
<em>Undergrad</em>: "That wasn't quite right - <em>this</em> is how the weather works."<br>
<em>Postgrad</em>: "That wasn't quite right - <em>this</em> is how the weather works."<br>
<em>Doctorate</em>: "Nobody knows how the weather works." </p>
</blockquote>
<p>... Nevertheless, the actual concept is pretty simply stated, once we get everything laid out. In brief, time dilation is when time appears to slow down for an object, when that object is moving very quickly. There are three important parts to that:</p>
<ul>
<li>the slowing of time; </li>
<li>the fact that it looks <em>to you</em> as if time has slowed <em>for the object</em>;</li>
<li>the object travelling quickly <em>relative to you</em>. </li>
</ul>
<p>That means, if your twin travels (around Europe, say) at the speed of light for "ten years" (your time), <strong>you</strong> will age ten years, but they will hardly age at all.</p>
<p>That's pretty weird - why does that happen? We can understand where time dilation comes from by remembering a few things:</p>
<ul>
<li>We all know that the universe's speed limit is the speed of light, <em>c</em>.</li>
<li>We're all familiar with the three dimensions of motion.</li>
<li>We've probably heard someone say "time is the fourth dimension" (aka "Minkowski spacetime").</li>
</ul>
<p>Here's the thing about speed limits: they apply whether you're moving in a straight line, or if you're moving on an angle. Imagine a box, a hundred kilometers square. If you travel a hundred kilometers from left-to-right, you will start at one edge of the box, and finish at the other. But if you start at the top-left corner of the box, and travel towards the bottom-right corner of the box, <em>and still travel a hundred kilometers</em>, you will end up only about 70% of the way to your destination... because some of your motion has been 'used up' travelling in the up/down direction, instead of just the left/right direction.</p>
<p>Now, here's the thing: you're <strong>always</strong> travelling at <em>c</em>. It's just that mostly you're travelling through <u><em>time</em></u> at the speed of light. Any movement in the other three dimensions will 'use up' your speed through the time dimension (because your total speed can't be faster than <em>c</em>). Quick examples:</p>
<p>You, sitting here now reading this:</p>
<div class="highlight"><pre><span></span><code><span class="err">Speed in x dimension: 0km per second</span>
<span class="err">Speed in t dimension: 299,793km per second</span>
</code></pre></div>
<p>You, 20 years from now, travelling away from Earth at a currently-safe velocity of 3G's (29.42 meters per second):</p>
<div class="highlight"><pre><span></span><code><span class="err">Speed in x dimension: 0.02942km per second</span>
<span class="err">Speed in t dimension: 299,792.97058km per second</span>
</code></pre></div>
<p>You, 200 years from now, travelling away from Aldeberan at a somehow-safe-by-then velocity of 300G (2942 meters per second):</p>
<div class="highlight"><pre><span></span><code><span class="err">Speed in x dimension: 29.42km per second</span>
<span class="err">Speed in t dimension: 299,763.58km per second</span>
</code></pre></div>
<p>You, never, travelling away from the milky way at 95% of the speed of light:</p>
<div class="highlight"><pre><span></span><code><span class="err">Speed in x dimension: 284,803km per second</span>
<span class="err">Speed in t dimension: 14,989km per second</span>
</code></pre></div>
<p>So, as you get faster in one dimension, you necessarily <em>must</em> move more slowly through time! Time dilation comes down to that, plus the hard-to-grasp concept that you're only either accelerating <em>or</em> stationary in your own frame of reference... but that's a story for another day.</p>
<p>That pretty much exhausts everything I know about time dilation... I hope you enjoyed reading it. Huge thanks to Ellie for finding me a friendly physicist to check over this for me!</p>
<p>In case you're looking for some good books on the science of the very fast, the very big, the very heavy, and the very small... Here are some books that I really enjoyed reading:</p>
<ul>
<li>Brian Greene - The Elegant Universe</li>
<li>Marcus Chown - Quantum Theory Cannot Hurt You</li>
<li>Michio Kaku - Einstein's Cosmos</li>
</ul>Inside the Check Point 11802019-04-28T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2019-04-28:/inside-the-check-point-1180.html<p>I've got a spare Check Point 1180 here, and I'm fiddling around with it a bit. Learnings so far:</p>
<ul>
<li>Platform: ARM</li>
<li>CPU / RAM: <a href="https://community.checkpoint.com/t5/General-Topics/I-have-a-Check-Point-model-L-50-serial-number-1310436119900-and/td-p/32165">ARM926EJ-S</a>, 512MB RAM</li>
<li>System board: Marvell RD-88f6281A LE</li>
</ul>When a docking station wrecks your breakfast2019-02-23T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2019-02-23:/when-a-docking-station-wrecks-your-breakfast.html<p>It's been a while since I posted, but we bumped into something completely batshit crazy at work that I just had to share.</p>
<p>One of my colleagues was setting up a new computer, and was unable to RDP into the new build. He kept getting the error message "Your session ended because there was a data encryption error. If this keeps happening, ask your admin or tech support for help."</p>
<p><img alt=""Your session ended because there was a data encryption error."" src="https://www.ericlight.com/images/wd15.png"></p>
<p>We'd never experienced this error before, and - although the internet knew about it - there were not very many helpful hits …</p><p>It's been a while since I posted, but we bumped into something completely batshit crazy at work that I just had to share.</p>
<p>One of my colleagues was setting up a new computer, and was unable to RDP into the new build. He kept getting the error message "Your session ended because there was a data encryption error. If this keeps happening, ask your admin or tech support for help."</p>
<p><img alt=""Your session ended because there was a data encryption error."" src="https://www.ericlight.com/images/wd15.png"></p>
<p>We'd never experienced this error before, and - although the internet knew about it - there were not very many helpful hits on Google. In fact, all of the reports we found were the result of a bug in Windows 7, and we were only using Windows 10.</p>
<p>In the end, completely weirdly, my colleague tried a different docking station, and it <em>worked</em>! This is absolutely the weirdest thing I've ever seen. Both the working and failing docking station had the most recent firmware applied, and they were both flashed from the same image, so it's not a corrupted download or anything.</p>
<p>Metadata about this issue: Both machines were Windows 10, 1709 build, with all updates installed. The originator machine was an HP Z240 workstation, and the target machine was a Dell 7390, connected to a Dell WD15 docking station. All three items had received fresh firmware updates and all Windows Updates.</p>American Crew's Moisturising Shave Cream2018-12-29T00:00:00+13:002020-11-24T21:28:25+13:00Eric Lighttag:www.ericlight.com,2018-12-29:/american-crews-moisturising-shave-cream.html<p>Yanno <a href="https://www.ericlight.com/proraso-azur-lime-aftershave-balm.html">how I said</a> it's hard to find American Crew aftershave? Well my better half went out yesterday and found a place in lil'old Te Awamutu that sells their shaving range: <a href="https://www.teamseven.co.nz">Team Seven</a>, beside Viands. She bought me a bottle of my favourite "<a href="https://shop.americancrew.com/post-shave-cooling-lotion">Post-Shave Cooling Lotion</a>" (oh my god that name), but also got me a tube of their "<a href="https://shop.americancrew.com/moisturizing-shave-cream">Moisturising Shave Cream</a>" to try. For shiggles.</p>
<p>Clearly, American Crew are better at chemical formulation than they are at coming up with names. But I digress.</p>
<p>Whelp I whipped out my …</p><p>Yanno <a href="https://www.ericlight.com/proraso-azur-lime-aftershave-balm.html">how I said</a> it's hard to find American Crew aftershave? Well my better half went out yesterday and found a place in lil'old Te Awamutu that sells their shaving range: <a href="https://www.teamseven.co.nz">Team Seven</a>, beside Viands. She bought me a bottle of my favourite "<a href="https://shop.americancrew.com/post-shave-cooling-lotion">Post-Shave Cooling Lotion</a>" (oh my god that name), but also got me a tube of their "<a href="https://shop.americancrew.com/moisturizing-shave-cream">Moisturising Shave Cream</a>" to try. For shiggles.</p>
<p>Clearly, American Crew are better at chemical formulation than they are at coming up with names. But I digress.</p>
<p>Whelp I whipped out my trusty DE89, popped in a fresh Derby Extra blade, soaked my shaving brush and gave it a go.</p>
<p>Firstly - no. This is absolutely not made for a shaving brush. It's hand-application all the way. It's also not really a foam like what I'm used to - it's very much a cream style, and it's quite stubborn about remaining a cream, thankyouverymuch. In contrast, my <a href="https://fineshave.co.nz/products/proraso-sensitive-green-tea-and-oat-shaving-cream-t">Proraso</a> or <a href="https://fineshave.co.nz/products/taylor-of-old-bond-street-shave-cream-sandalwood">TOBS</a> creams froth up quite heartily when I whip them with a brush, but this really resisted that.</p>
<p>Okay so, without making it frothy, it definitely takes more product to shave. I'm going to say double, but it might even be more. At about $32 a tube, that is definitely verging out of my price range. 2/10 on price for this.</p>
<p>The feeling, however, was really divine. There's not a whole lot of scent, but there's significant menthol action going on here, and it really gave me a refreshing zing that dwindled on my face through the shave and rinse. Delight rating 7/10.</p>
<p>Efficacy - this is hard for me to judge, since I was using a brush and thus really didn't have enough on there for my second pass. So I kinda mucked up my shave, but it was much more my fault than the cream's. Aside from that it left a beautiful coating of light avocado oil and aloe on my skin, meaning even though I under-catered on the product, I didn't entirely munge up my face. For this, I'm giving it a decent 7/10 on efficacy. (See update below, though)</p>
<p>These ratings seem kinda low, but honestly this is going to be my favourite shave cream through the summer, with that nice refreshing menthol coolness. However with the price and sheer quantity needed for a good shave, I expect I'll gravitate back to my Proraso creams once this is gone.</p>
<p><strong>Update 2018-12-31:</strong> I've had another shave today without the brush, and just applying the cream directly to my skin. Definitely a better result, but once again I under-catered on the second pass and got myself some irritation happening. It's certainly going to be at least double what I previously used. However once again my face feels actually quite good, and geez the menthol is nice.</p>
<p>Since I've under-catered twice now, and both times I've actually still had a decent shave, I think I need to upgrade this to 8/10 efficacy.</p>Proraso Azur Lime aftershave balm2018-12-28T00:00:00+13:002020-11-24T21:28:25+13:00Eric Lighttag:www.ericlight.com,2018-12-28:/proraso-azur-lime-aftershave-balm.html<p>Gather around, children, and I'll regale you with a tale of tonight's shaving.</p>
<p>My go-to razor setup at the moment is my <a href="https://fineshave.co.nz/products/edwin-jagger-de89-safety-razor-with-barley-handle">Edwin Jagger DE89</a>, with <a href="https://fineshave.co.nz/products/blades-50x-derby-de-razor-blades">Derby Extra</a> blades. But that's not new.</p>
<p>You might remember that my favourite aftershave is American Crew's "<a href="https://shop.americancrew.com/post-shave-cooling-lotion">Post Shave Cooling Lotion</a>". I've been using this almost exclusively for about 5 years now, and I love it. It's wonderfully soothing, and it's a fairly thin balm so it's easy to avoid overly-thick application. It's also not as thin as a milk (such as "<a href="https://www.thegr.com/shop-2/after-shave-balm/the-standard-after-shave-balm-all-natural-and-organic/">The Standard …</a></p><p>Gather around, children, and I'll regale you with a tale of tonight's shaving.</p>
<p>My go-to razor setup at the moment is my <a href="https://fineshave.co.nz/products/edwin-jagger-de89-safety-razor-with-barley-handle">Edwin Jagger DE89</a>, with <a href="https://fineshave.co.nz/products/blades-50x-derby-de-razor-blades">Derby Extra</a> blades. But that's not new.</p>
<p>You might remember that my favourite aftershave is American Crew's "<a href="https://shop.americancrew.com/post-shave-cooling-lotion">Post Shave Cooling Lotion</a>". I've been using this almost exclusively for about 5 years now, and I love it. It's wonderfully soothing, and it's a fairly thin balm so it's easy to avoid overly-thick application. It's also not as thin as a milk (such as "<a href="https://www.thegr.com/shop-2/after-shave-balm/the-standard-after-shave-balm-all-natural-and-organic/">The Standard</a>", by The Gentlemen's Refinery), which has a tendency to run through your fingers on the way to your face, not entirely unlike... milk.</p>
<p>Unfortunately American Crew's aftershave can be really difficult to find. So I popped a question to the team at <a href="https://fineshave.co.nz">FineShave</a>, and Frank gave me some insight into what he uses. This spurred me to try the <a href="https://fineshave.co.nz/collections/aftershave/proraso">Proraso Aftershave line</a>, and today I took delivery of a bottle of <a href="https://fineshave.co.nz/collections/aftershave/products/proraso-after-shave-balm-azur-lime-100ml">Azur Lime</a>.</p>
<p>This is a really, really nice aftershave. Again, it's a balm (I don't have any splash-type aftershaves yet). It's a little thicker than the American Crew that I'm used to, but still not thick.</p>
<p>WOW does it cover a lot of distance. I used three, maybe four drops worth and it covered my whole face. This 100ml bottle is going to last forever, but it's still a bit pricey at $35, which makes me give it a 6/10 on the price scale.</p>
<p>It's a light citrusy scent, with a little bit of mint, and a slightly musky underbelly. It smells nice, but the scent wears off fairly quickly, so probably a 7/10 for scent.</p>
<p>I also happened to give myself a spectacularly awful shave, which this aftershave has completely addressed - no discomfort or 'hot areas', and only a little redness in the mirror. I think that's a 10/10 for effectiveness.</p>
<p>All in all, this is a serious contender for my new favourite, and I expect I'll buy another bottle when it's done! Recommended.</p>New things I didn't know about WireGuard2018-12-27T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2018-12-27:/new-things-i-didnt-know-about-wireguard.html<p>This is part of my <a href="https://www.ericlight.com/wireguard-part-one-installation.html">brief</a> <a href="https://www.ericlight.com/wireguard-part-two-vpn-routing.html">series</a> <a href="https://www.ericlight.com/wireguard-part-three-troubleshooting.html">on</a> <a href="https://wireguard.com/">WireGuard</a>. I'm pretty enamoured with WireGuard and the way it works, and I've been using it pretty seamlessly for over a year now. I've learned a couple things that weren't immediately obvious though, so I'm documenting them here.</p>
<h2>Easy Provisioning</h2>
<p>Samuel Holland mentioned an interesting trinket, in his post at <a href="https://lists.zx2c4.com/pipermail/WireGuard/2018-December/003703.html">https://lists.zx2c4.com/pipermail/WireGuard/2018-December/003703.html</a>:</p>
<p><em>"[...] WireGuard will ignore a peer whose public key matches the interface's private key. So you can distribute a single list of peers everywhere …</em></p><p>This is part of my <a href="https://www.ericlight.com/wireguard-part-one-installation.html">brief</a> <a href="https://www.ericlight.com/wireguard-part-two-vpn-routing.html">series</a> <a href="https://www.ericlight.com/wireguard-part-three-troubleshooting.html">on</a> <a href="https://wireguard.com/">WireGuard</a>. I'm pretty enamoured with WireGuard and the way it works, and I've been using it pretty seamlessly for over a year now. I've learned a couple things that weren't immediately obvious though, so I'm documenting them here.</p>
<h2>Easy Provisioning</h2>
<p>Samuel Holland mentioned an interesting trinket, in his post at <a href="https://lists.zx2c4.com/pipermail/WireGuard/2018-December/003703.html">https://lists.zx2c4.com/pipermail/WireGuard/2018-December/003703.html</a>:</p>
<p><em>"[...] WireGuard will ignore a peer whose public key matches the interface's private key. So you can distribute a single list of peers everywhere."</em></p>
<p>You can combine this with <code>wg addconf</code> like this:</p>
<ul>
<li>Each peer has its own <code>/etc/WireGuard/wg0.conf</code> file, which only contains it's <code>[Interface]</code> section</li>
<li>Each peer also has a shared <code>/etc/WireGuard/peers.conf</code> file, which contains all the peers</li>
<li>The <code>wg0.conf</code> file also has a PostUp hook, calling <code>wg addconf /etc/WireGuard/peers.conf</code></li>
</ul>
<p>It's up to you to decide how you want to share the peers.conf, be it via a proper orchestration platform, something much more pedestrian like Dropbox, or something kinda wild like Ceph. I dunno, but it's pretty great that you can just wildly fling a peer section around, without worrying whether it's the same as the interface. </p>
<h2>Setting Private Key from a file</h2>
<p>Another piece of learning, courtesy of Samuel Holland, at <a href="https://lists.zx2c4.com/pipermail/WireGuard/2018-December/003702.html">https://lists.zx2c4.com/pipermail/WireGuard/2018-December/003702.html</a>.</p>
<p>You can read in a file as the Private Key by doing something like:</p>
<p><code>PostUp = wg set %i private-key /etc/WireGuard/wg0.key</code></p>Tomato Soup2018-05-07T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2018-05-07:/tomato-soup.html<p>I came home tonight to discover my wife had made probably the most amazing tomato soup I've ever tasted. She performed this feat with about ten minutes of effort (plus about an hour of simmering), so I decided I needed to note it down.</p>
<h1>Ingredients</h1>
<ul>
<li>1 Tbsp oil</li>
<li>1 medium onion, sliced</li>
<li>1/2 head of garlic, peeled and chopped</li>
<li>About 4 slices of bacon, diced</li>
<li>3 cans of chopped tomatoes</li>
<li>2 tsp of vegetable stock powder</li>
<li>2 tsp of sugar</li>
<li>1 cup of water</li>
<li>Cream</li>
<li>Parsley for garnish</li>
</ul>
<h1>Method …</h1><p>I came home tonight to discover my wife had made probably the most amazing tomato soup I've ever tasted. She performed this feat with about ten minutes of effort (plus about an hour of simmering), so I decided I needed to note it down.</p>
<h1>Ingredients</h1>
<ul>
<li>1 Tbsp oil</li>
<li>1 medium onion, sliced</li>
<li>1/2 head of garlic, peeled and chopped</li>
<li>About 4 slices of bacon, diced</li>
<li>3 cans of chopped tomatoes</li>
<li>2 tsp of vegetable stock powder</li>
<li>2 tsp of sugar</li>
<li>1 cup of water</li>
<li>Cream</li>
<li>Parsley for garnish</li>
</ul>
<h1>Method</h1>
<ol>
<li>Get yourself a piping-hot frying pan</li>
<li>Add the oil and the onion; fry until transluscent</li>
<li>Add the garlic and the bacon; fry until bacon starts to brown</li>
<li>Add chopped tomatoes, veggie stock, and water; stir</li>
<li>Simmer for at least 45 minutes; preferrably longer</li>
<li>Serve with a dollop of cream, and garnish with parsley</li>
</ol>
<p>That's it! It's hands-down delicious.</p>When AppArmor eats your breakfast2018-03-19T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2018-03-19:/when-apparmor-eats-your-breakfast.html<p>I've knocked heads with AppArmor a few times now. To be quite honest with myself, I think it's primarily because I install it, enable all the plugins, and then forget it's there until there's a problem.</p>
<p><strong>TL;DR:</strong></p>
<p>On a fully-updated Zentyal 5.0 system running DHCP, the AppArmor profile in /etc/apparmor.d/usr.sbin.dhcpd <strong>will prevent isc-dhcp-server from restarting itself after an upgrade</strong>.</p>
<p>More search-type words: Zentyal dhcp server doesn't start again after upgrade. isc-dhcp-server graceful shutdown, but no restart.</p>
<p>This frustration-laden, Google-friendly equivalent of speaking slowly …</p><p>I've knocked heads with AppArmor a few times now. To be quite honest with myself, I think it's primarily because I install it, enable all the plugins, and then forget it's there until there's a problem.</p>
<p><strong>TL;DR:</strong></p>
<p>On a fully-updated Zentyal 5.0 system running DHCP, the AppArmor profile in /etc/apparmor.d/usr.sbin.dhcpd <strong>will prevent isc-dhcp-server from restarting itself after an upgrade</strong>.</p>
<p>More search-type words: Zentyal dhcp server doesn't start again after upgrade. isc-dhcp-server graceful shutdown, but no restart.</p>
<p>This frustration-laden, Google-friendly equivalent of speaking slowly and clearly should illustrate how impossible it was for me to find guidance on this.</p>
<p>To fix:</p>
<div class="highlight"><pre><span></span><code><span class="err"># aa-complain /etc/apparmor.d/usr.sbin.dhcpd </span>
</code></pre></div>
<hr>
<p>Okay, now that the TL;DR is finished, here's the rest of the story:</p>
<p>Unfortunately there's <strong>always</strong> a problem with AppArmor eventually.</p>
<p>Even worse, <em>the problem is often silent</em>. I'll just find that, for example, NONE of my man pages work. Or logrotate will fail. For example, here's what happens when you enable aa-enforce mode on your friendly resident user manual:</p>
<div class="highlight"><pre><span></span><code><span class="err"> $ man</span>
<span class="err"> What manual page do you want?</span>
<span class="err"> $ sudo aa-enforce /etc/apparmor.d/usr.bin.man</span>
<span class="err"> Setting /etc/apparmor.d/usr.bin.man to enforce mode.</span>
<span class="err"> $ man</span>
<span class="err"> $man: can't open the manpath configuration file /etc/manpath.config</span>
</code></pre></div>
<p>If I hadn't enabled <code>aa-enforce</code> immediately before that, what would <em>you</em> have done? You would have gone ahead, made sure that manpath.config existed, made sure it wasn't corrupted, maybe tried running <code>man</code> as root... maybe even copied a manpath.config file from a known-working computer. But, hidden within <code>dmesg</code> is our old friend:</p>
<p><code>[149929.763064] type=1400 audit(1521449052.257:111): apparmor="DENIED" operation="open" profile="/usr/bin/man" name="/etc/manpath.config" pid=22633 comm="man" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0</code></p>
<p>And that example is actually better than it used to be - quite a few times in the past four years, I've received this:</p>
<div class="highlight"><pre><span></span><code>$ man
$
</code></pre></div>
<p>... from a fully-updated Debian system.</p>
<p><br/><br/>
<em>This makes me sad.</em>
<br/><br/></p>
<p>Or, in one particular case, <em>ISC-DHCP-SERVER</em> of all things will launch perfectly well, but will fail to restart after a package update, and the first thing I'll notice is "o hai all the things is broken halp plz". Something like that.</p>
<p>When you're troubleshooting DHCP, you'll probably check systemctl, leases table, maybe /var/log ... But when you get around to checking <code>dmesg</code>, you may notice the root of the problem:</p>
<p>From dmesg -T:</p>
<div class="highlight"><pre><span></span><code><span class="err">[Sat Mar 17 03:44:28 2016] audit_printk_skb: 18 callbacks suppressed</span>
</code></pre></div>
<p>Considering the update occurred at 03:44am, this is probably our problem. I can't see <em>for sure</em>, but I'm pretty certain those 18 suppressed callbacks are filled with "DENIED" log lines.</p>
<p>The fix is simple:</p>
<div class="highlight"><pre><span></span><code><span class="err"># aa-complain /etc/apparmor.d/usr.sbin.dhcpd </span>
<span class="err">Setting /etc/apparmor.d/usr.sbin.dhcpd to complain mode.</span>
</code></pre></div>
<p>And your isc-dhcp-server should now restart gracefully after it's scheduled upgrades!</p>Installing PowerChute Network Shutdown on ProxmoxVE2018-02-27T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2018-02-27:/installing-powerchute-network-shutdown-on-proxmoxve.html<p>This is going to be one of those posts where I just dump stuff. Power failures are shite, and if your server isn't talking with your UPS, it won't shut down gracefully. This is the story of my trying to get APC's PowerChute Network Shutdown working on a ProxmoxVE 5.1 environment.</p>
<p>Note I opted out of using either nut or apcupsd, because I had a nice fancy Network Management Card (NMC2 / Schneider AP9631) available. Also, I wanted to shut down more than a single server, so a USB or …</p><p>This is going to be one of those posts where I just dump stuff. Power failures are shite, and if your server isn't talking with your UPS, it won't shut down gracefully. This is the story of my trying to get APC's PowerChute Network Shutdown working on a ProxmoxVE 5.1 environment.</p>
<p>Note I opted out of using either nut or apcupsd, because I had a nice fancy Network Management Card (NMC2 / Schneider AP9631) available. Also, I wanted to shut down more than a single server, so a USB or Serial cable wouldn't do the trick.</p>
<ol>
<li>Install Java Runtime Environment: <code>apt install openjdk-8-jre</code></li>
<li>Download PCNS onto your Proxmox server - <a href="http://www.apc.com/shop/us/en/categories/power/uninterruptible-power-supply-ups-/ups-management/powerchute-network-shutdown/N-auzzn7">http://www.apc.com/shop/us/en/categories/power/uninterruptible-power-supply-ups-/ups-management/powerchute-network-shutdown/N-auzzn7</a></li>
<li>Extract the download: <code>tar -xvf pcns420Linux-x86-64.tar.gz</code></li>
<li>cd ./Linux_x64</li>
<li>sudo su</li>
<li>./install.sh</li>
<li>When prompted for your Java location, use <code>/usr/lib/jvm/java-8-openjdk-amd64/jre/bin</code></li>
<li>I didn't enable SMTP</li>
</ol>
<p>Results in:</p>
<div class="highlight"><pre><span></span><code> <span class="n">root</span><span class="o">@</span> <span class="o">~/</span><span class="n">Linux_x64</span><span class="o">#</span> <span class="p">.</span><span class="o">/</span><span class="n">install</span><span class="p">.</span><span class="n">sh</span>
<span class="c1">------------------------------------------------------------------</span>
<span class="n">PowerChute</span> <span class="n">Network</span> <span class="n">Shutdown</span> <span class="mi">4</span><span class="p">.</span><span class="mi">2</span><span class="p">.</span><span class="mi">0</span> <span class="k">for</span> <span class="n">Linux</span>
<span class="n">Copyright</span> <span class="p">(</span><span class="k">c</span><span class="p">)</span> <span class="mi">1999</span><span class="o">-</span><span class="mi">2016</span> <span class="n">Schneider</span> <span class="n">Electric</span><span class="p">.</span>
<span class="k">All</span> <span class="n">Rights</span> <span class="n">Reserved</span><span class="p">.</span>
<span class="c1">------------------------------------------------------------------</span>
<span class="n">OS</span><span class="o">=</span><span class="n">Linux</span>
<span class="n">Initializing</span> <span class="p">...</span>
<span class="n">Press</span> <span class="k">any</span> <span class="k">key</span> <span class="k">to</span> <span class="n">display</span> <span class="k">End</span> <span class="k">User</span> <span class="n">License</span> <span class="n">Agreement</span>
<span class="o"><</span><span class="c1">--snip--></span>
<span class="k">Do</span> <span class="n">you</span> <span class="n">agree</span> <span class="k">to</span> <span class="n">the</span> <span class="n">above</span> <span class="n">license</span> <span class="n">terms</span><span class="o">?</span> <span class="p">[</span><span class="n">yes</span> <span class="k">or</span> <span class="k">no</span><span class="p">]</span>
<span class="n">yes</span>
<span class="n">Please</span> <span class="n">enter</span> <span class="n">the</span> <span class="n">installation</span> <span class="n">directory</span> <span class="k">or</span> <span class="n">press</span> <span class="n">enter</span> <span class="k">to</span> <span class="n">install</span> <span class="k">to</span> <span class="n">the</span> <span class="k">default</span> <span class="n">directory</span> <span class="p">(</span><span class="o">/</span><span class="n">opt</span><span class="o">/</span><span class="n">APC</span><span class="o">/</span><span class="n">PowerChute</span><span class="p">):</span>
<span class="k">Are</span> <span class="n">you</span> <span class="n">sure</span> <span class="n">you</span> <span class="n">want</span> <span class="k">to</span> <span class="n">install</span> <span class="n">PCNS</span> <span class="k">to</span> <span class="o">/</span><span class="n">opt</span><span class="o">/</span><span class="n">APC</span><span class="o">/</span><span class="n">PowerChute</span> <span class="p">[</span><span class="n">Yes</span><span class="o">|</span><span class="k">No</span><span class="p">]</span><span class="o">?</span>
<span class="n">yes</span>
<span class="n">PCNS</span> <span class="n">will</span> <span class="n">be</span> <span class="n">installed</span> <span class="k">to</span> <span class="o">/</span><span class="n">opt</span><span class="o">/</span><span class="n">APC</span><span class="o">/</span><span class="n">PowerChute</span>
<span class="n">Please</span> <span class="n">enter</span> <span class="n">java</span> <span class="n">directory</span> <span class="k">if</span> <span class="n">you</span> <span class="n">want</span> <span class="k">to</span> <span class="n">use</span> <span class="n">your</span> <span class="k">system</span> <span class="n">java</span> <span class="p">(</span><span class="n">example</span><span class="p">:</span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="k">local</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">jre</span><span class="o">/</span><span class="n">jre1</span><span class="p">.</span><span class="mi">8</span><span class="p">.</span><span class="mi">0</span><span class="n">_91</span><span class="p">)</span> <span class="k">or</span> <span class="n">press</span> <span class="n">enter</span> <span class="k">to</span> <span class="n">install</span> <span class="n">the</span> <span class="n">bundled</span> <span class="n">Java</span><span class="p">:</span>
<span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">jvm</span><span class="o">/</span><span class="n">java</span><span class="o">-</span><span class="mi">8</span><span class="o">-</span><span class="n">openjdk</span><span class="o">-</span><span class="n">amd64</span><span class="o">/</span><span class="n">jre</span><span class="o">/</span><span class="n">bin</span>
<span class="n">Checking</span> <span class="k">version</span> <span class="k">of</span> <span class="n">Java</span> <span class="p">...</span>
<span class="n">Detected</span> <span class="n">Java</span> <span class="k">Version</span><span class="p">:</span> <span class="mi">1</span><span class="p">.</span><span class="mi">8</span><span class="p">.</span><span class="mi">0</span><span class="p">.</span><span class="mi">151</span>
<span class="n">Acceptable</span> <span class="k">version</span>
<span class="n">openjdk</span> <span class="k">version</span> <span class="ss">"1.8.0_151"</span>
<span class="n">OpenJDK</span> <span class="n">Runtime</span> <span class="n">Environment</span> <span class="p">(</span><span class="n">build</span> <span class="mi">1</span><span class="p">.</span><span class="mi">8</span><span class="p">.</span><span class="mi">0</span><span class="n">_151</span><span class="o">-</span><span class="mi">8</span><span class="n">u151</span><span class="o">-</span><span class="n">b12</span><span class="o">-</span><span class="mi">1</span><span class="o">~</span><span class="n">deb9u1</span><span class="o">-</span><span class="n">b12</span><span class="p">)</span>
<span class="n">OpenJDK</span> <span class="mi">64</span><span class="o">-</span><span class="nb">Bit</span> <span class="n">Server</span> <span class="n">VM</span> <span class="p">(</span><span class="n">build</span> <span class="mi">25</span><span class="p">.</span><span class="mi">151</span><span class="o">-</span><span class="n">b12</span><span class="p">,</span> <span class="n">mixed</span> <span class="k">mode</span><span class="p">)</span>
<span class="n">JAVA_DIR</span><span class="o">=/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">jvm</span><span class="o">/</span><span class="n">java</span><span class="o">-</span><span class="mi">8</span><span class="o">-</span><span class="n">openjdk</span><span class="o">-</span><span class="n">amd64</span><span class="o">/</span><span class="n">jre</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span>
<span class="n">Copying</span> <span class="n">the</span> <span class="n">installation</span> <span class="n">files</span> <span class="p">...</span>
<span class="n">Extracting</span> <span class="n">PCNS</span> <span class="n">files</span> <span class="p">...</span>
<span class="n">PCNS</span> <span class="k">is</span> <span class="n">extracted</span> <span class="k">to</span> <span class="o">/</span><span class="n">opt</span><span class="o">/</span><span class="n">APC</span><span class="o">/</span><span class="n">PowerChute</span>
<span class="n">Configuring</span> <span class="n">startup</span> <span class="n">files</span> <span class="p">...</span>
<span class="n">Startup</span> <span class="n">script</span><span class="o">=/</span><span class="n">etc</span><span class="o">/</span><span class="n">rc</span><span class="p">.</span><span class="n">d</span><span class="o">/</span><span class="n">init</span><span class="p">.</span><span class="n">d</span><span class="o">/</span><span class="n">PowerChute</span>
<span class="n">Updating</span> <span class="n">Linux</span> <span class="n">symbolic</span> <span class="n">link</span> <span class="p">...</span>
<span class="n">Configure</span> <span class="n">Firewall</span>
<span class="n">Configuring</span> <span class="n">uninstall</span> <span class="n">script</span> <span class="p">...</span>
<span class="n">Setup</span> <span class="n">the</span> <span class="n">m11</span><span class="p">.</span><span class="n">cfg</span> <span class="n">file</span>
<span class="n">Enable</span> <span class="n">SNMP</span> <span class="n">Support</span> <span class="p">[</span><span class="n">Yes</span><span class="o">|</span><span class="k">No</span><span class="p">]</span><span class="o">?</span>
<span class="k">no</span>
<span class="n">SNMP</span> <span class="k">Not</span> <span class="n">Enabled</span>
<span class="n">PowerChute</span> <span class="n">Network</span> <span class="n">Shutdown</span><span class="p">,</span> <span class="n">v4</span><span class="p">.</span><span class="mi">2</span><span class="p">.</span><span class="mi">0</span>
<span class="n">Copyright</span> <span class="p">(</span><span class="k">c</span><span class="p">)</span> <span class="mi">1999</span><span class="o">-</span><span class="mi">2016</span><span class="p">,</span> <span class="n">Schneider</span> <span class="n">Electric</span><span class="p">.</span> <span class="k">All</span> <span class="n">Rights</span> <span class="n">Reserved</span><span class="p">.</span>
<span class="n">Startup</span> <span class="n">completed</span><span class="p">.</span>
<span class="n">Installation</span> <span class="n">has</span> <span class="n">completed</span><span class="p">.</span>
<span class="n">PowerChute</span> <span class="n">Network</span> <span class="n">Shutdown</span> <span class="n">can</span> <span class="n">be</span> <span class="n">accessed</span> <span class="n">through</span> <span class="n">your</span> <span class="n">browser</span> <span class="k">at</span> <span class="n">https</span><span class="p">:</span><span class="o">//<</span><span class="n">your_server_ip_address</span><span class="o">></span><span class="p">:</span><span class="mi">6547</span>
<span class="n">Please</span> <span class="n">complete</span> <span class="n">the</span> <span class="n">configuration</span> <span class="n">wizard</span> <span class="n">so</span> <span class="n">that</span> <span class="n">PowerChute</span> <span class="n">Network</span> <span class="n">Shutdown</span> <span class="n">can</span> <span class="n">protect</span> <span class="n">your</span> <span class="n">server</span><span class="p">.</span>
</code></pre></div>
<p>Once you're finished with that, navigate to the new web portal on your server (second-to-last line in the output above), and complete the setup of your PCNS instance!</p>
<p>When you're configuring PCNS itself, you'll be prompted for the User Name, Password, and Authentication Phrase for the UPS. These are the user details you use to log into your NMC.</p>
<p>By default, the Authentication Phrase is <code>admin user phrase</code>, but you should <em>totally</em> change this. Assuming you've updated the firmware on your NMC, you can set the Authentication Phrase at <code>Configuration -> Shutdown</code>.</p>
<p>Setting up your outlet groups and shutdown times are left as an exercise to the reader. :)</p>Getting rid of the # format in Flex2018-01-12T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2018-01-12:/getting-rid-of-the-format-in-flex.html<p>Back when I was getting this blog set up, I had a <a href="https://www.ericlight.com/tidying-up-pelicans-urls-with-the-flex-theme.html">short whinge</a> about the default way that the <a href="https://github.com/alexandrevicenzi/Flex">Flex theme</a> created links to pages.</p>
<p>Specficially, creating a link to "<a href="https://www.ericlight.com/tuna-patties.html">Tuna Patties</a>" (for example), Flex would append the link with an identical stub, such as <a href="https://www.ericlight.com/tuna-patties.html#tuna-patties">https://www.ericlight.com/tuna-patties.html#tuna-patties</a></p>
<p>I thought this was silly, so I found a way to fix it, but never bothered submitting a Pull Request to Alexandre because I figured it was intentional.</p>
<p>Well, it turns out I wasn't the only one …</p><p>Back when I was getting this blog set up, I had a <a href="https://www.ericlight.com/tidying-up-pelicans-urls-with-the-flex-theme.html">short whinge</a> about the default way that the <a href="https://github.com/alexandrevicenzi/Flex">Flex theme</a> created links to pages.</p>
<p>Specficially, creating a link to "<a href="https://www.ericlight.com/tuna-patties.html">Tuna Patties</a>" (for example), Flex would append the link with an identical stub, such as <a href="https://www.ericlight.com/tuna-patties.html#tuna-patties">https://www.ericlight.com/tuna-patties.html#tuna-patties</a></p>
<p>I thought this was silly, so I found a way to fix it, but never bothered submitting a Pull Request to Alexandre because I figured it was intentional.</p>
<p>Well, it turns out I wasn't the only one. The good <a href="https://github.com/DmytroLitvinov">Dmytro Litvinov</a> thought the same, and he created a <a href="https://github.com/alexandrevicenzi/Flex/pull/88">Pull Request</a> to fix it, almost a whole year ago!</p>
<p>Now, you can avoid this behaviour by simply adding <code>DISABLE_URL_HASH = True</code> to your <code>pelicanconf.py</code>!</p>Fix Dell Keyboard Backlight under Debian2018-01-11T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2018-01-11:/fix-dell-keyboard-backlight-under-debian.html<p>My personal laptop is an old Dell Latitude E6410. One of the things I actually love about it, is the fact that the keyboard has a backlight.</p>
<p>However, because Linux, sometimes that backlight just stops working. When this happens, you'll see error messages in dmesg, such as:</p>
<div class="highlight"><pre><span></span><code><span class="n">dell_wmi</span><span class="o">:</span> <span class="n">Unknown</span> <span class="n">key</span> <span class="k">with</span> <span class="n">type</span> <span class="mh">0x0011</span> <span class="n">and</span> <span class="n">code</span> <span class="mh">0x01e2</span> <span class="n">pressed</span>
</code></pre></div>
<p>If this happens to you, just run this command:</p>
<div class="highlight"><pre><span></span><code>$ sudo <span class="nb">echo</span> <span class="m">7</span> > /sys/devices/platform/dell-laptop/leds/dell<span class="se">\:\:</span>kbd_backlight/brightness
</code></pre></div>
<p>You can echo a higher number if you want your keyboard brighter, but …</p><p>My personal laptop is an old Dell Latitude E6410. One of the things I actually love about it, is the fact that the keyboard has a backlight.</p>
<p>However, because Linux, sometimes that backlight just stops working. When this happens, you'll see error messages in dmesg, such as:</p>
<div class="highlight"><pre><span></span><code><span class="n">dell_wmi</span><span class="o">:</span> <span class="n">Unknown</span> <span class="n">key</span> <span class="k">with</span> <span class="n">type</span> <span class="mh">0x0011</span> <span class="n">and</span> <span class="n">code</span> <span class="mh">0x01e2</span> <span class="n">pressed</span>
</code></pre></div>
<p>If this happens to you, just run this command:</p>
<div class="highlight"><pre><span></span><code>$ sudo <span class="nb">echo</span> <span class="m">7</span> > /sys/devices/platform/dell-laptop/leds/dell<span class="se">\:\:</span>kbd_backlight/brightness
</code></pre></div>
<p>You can echo a higher number if you want your keyboard brighter, but I found 7 to be more than bright enough.</p>Smokey BBQ-Baked Beans2018-01-10T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2018-01-10:/smokey-bbq-baked-beans.html<p>We recently got a <a href="https://fornetto.com/products/basso-vertical-smoker/">Fornetto Basso</a> - it's an 18" bullet smoker/barbecue, advertised with three tiers of deliciousness: two bbq racks, and a rail under the lid for hanging meats for smoking. It also has a large metal water bowl, which goes at the bottom. The water helps to keep the meat moist, and helps regulate the temperature.</p>
<p>However... The water bowl <strong>also</strong> turns out to be my new favourite bean-cooking vessel! It's quite huge (probably about 8 litres) and of course it doesn't consume any of the precious roasting …</p><p>We recently got a <a href="https://fornetto.com/products/basso-vertical-smoker/">Fornetto Basso</a> - it's an 18" bullet smoker/barbecue, advertised with three tiers of deliciousness: two bbq racks, and a rail under the lid for hanging meats for smoking. It also has a large metal water bowl, which goes at the bottom. The water helps to keep the meat moist, and helps regulate the temperature.</p>
<p>However... The water bowl <strong>also</strong> turns out to be my new favourite bean-cooking vessel! It's quite huge (probably about 8 litres) and of course it doesn't consume any of the precious roasting real-estate. Even better, the juices from your cooking meat will drip into the beans, bringing a nice smokey meaty flavour! ❤️</p>
<p>So anyway, I whipped up a recipe last night, and my awesome wife ran the smoker today while I was at work. I came home to the best baked beans I've ever tasted.</p>
<p>The following recipe is plenty for a good 6 people, and should provide some leftovers as well. We used a mix of Apple wood and Cherry wood for smoke.</p>
<figure align="center">
<img src="https://www.ericlight.com/images/cooking-beans.jpg" alt="The beans simmering - it's all still very liquid, all the beans are still firm and bean-shaped, and chunks of capsicum and onion are recognisable."/>
<figcaption><em>Part-way through the cook</em></figcaption>
</figure>
<h2>Ingredients</h2>
<ul>
<li>1 cup cooked bacon, chopped into about 2cm squares (optional)</li>
<li>6 cups mixed raw beans*, soaked in clean water overnight and drained</li>
<li>18 cups water</li>
<li>2 fairly large onions, diced large</li>
<li>3 capsicum (any colour), cut to about 2cm squares</li>
<li>2 Tbsp mustard</li>
<li>270ml of tomato sauce (I used Watties)</li>
<li>6 Tbsp dark brown sugar</li>
<li>8 Tbsp cider vinegar</li>
<li>4 Tbsp Worchestershire sauce</li>
<li>1/2 tsp cayenne pepper (possibly a bit less depending on taste)</li>
</ul>
<p><em>* I used a mix of about 40% haricot beans, 10% black beans, 30% red kidney beans, and 20% giant lima beans. The black beans were pleasant surprises, but the lima weren't particularly enlightening - get butter beans instead, if you can find them.</em></p>
<p>Mix all the ingredients together in your bowl (or a tray), pop it in the BBQ, and fire it up! The beans will absorb some of the water, and some of the water will evaporate to keep your meat hydrated. Your beans should be cooked by the time the sauce has thickened down - ours were ready in about 5 hours. Make sure you don't cook them dry!</p>
<p>Enjoy!</p>
<figure align="center">
<img src="https://www.ericlight.com/images/cooked-beans.jpg" alt="The liquid has thickened into a paste consistency; the beans are way softer, many are mashed and split. The capsicum peeks through in splashes of colour."/>
<figcaption><em>Utterly delicious ... although already mostly eaten!</em></figcaption>
</figure>Mikrotik RouterOS - incorrect SNMP status for idle WLAN interfaces2018-01-07T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2018-01-07:/mikrotik-routeros-incorrect-snmp-status-for-idle-wlan-interfaces.html<p>While trying to monitor the status of one of our wireless access points, I discovered that RouterOS returns an incorrect SNMP status code for the wlan interfaces when there are no clients connected to the interface. This is at least present in RouterOS v6.40.3, on a Mikrotik cAPlite (RBcAPL-2nD). </p>
<p>Specifically, when the wifi interface is <strong>up</strong>, but has zero connected clients, the OID returns an SNMP value of 2 ("down"). This status is incorrect - the interface isn't down, it's merely waiting for an external connection. </p>
<p>The specific OID …</p><p>While trying to monitor the status of one of our wireless access points, I discovered that RouterOS returns an incorrect SNMP status code for the wlan interfaces when there are no clients connected to the interface. This is at least present in RouterOS v6.40.3, on a Mikrotik cAPlite (RBcAPL-2nD). </p>
<p>Specifically, when the wifi interface is <strong>up</strong>, but has zero connected clients, the OID returns an SNMP value of 2 ("down"). This status is incorrect - the interface isn't down, it's merely waiting for an external connection. </p>
<p>The specific OID is 1.3.6.1.2.1.2.2.1.8.2 (iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifOperStatus - interface #2 in my case) </p>
<p>The applicable RFC says, "<em>When ifAdminStatus changes to the up state, the related ifOperStatus should do one of the following: [...] Change to the dormant state if and only if the interface is found to be operable, but the interface is waiting for other, external, events to occur before it can transmit or receive packets</em>" (<a href="https://www.ietf.org/rfc/rfc2863.txt">https://www.ietf.org/rfc/rfc2863.txt</a>, section 3.1.13) </p>
<p>I notice this issue was logged on the forums about 6 years ago, at <a href="https://forum.mikrotik.com/viewtopic.php?t=51332">https://forum.mikrotik.com/viewtopic.php?t=51332</a>. </p>
<p>I've raised this issue with Mikrotik support, and apparently it's been added to their to-do list, but I'm not sure it'll ever be done. In the meantime, we've just had to disable up/down monitoring of that specific interface, because it's so misleading.</p>When the problem is DNS: FreeNAS and NFS2018-01-07T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2018-01-07:/when-the-problem-is-dns-freenas-and-nfs.html<p>I discovered a while ago that NFS requires DNS to function correctly: <a href="https://redmine.ixsystems.com/issues/4983">https://redmine.ixsystems.com/issues/4983</a></p>
<p>That's somewhat annoying, because when your DNS server goes down (and your backups are stored on your FreeNAS server and accessed over NFS), is precisely the time when you really want your backups to be accessible.</p>
<p>However, turns out it doesn't <em>aaaaactuallyyyyy</em> need DNS... it needs <strong>name resolution</strong>. Specifically, FreeNAS just needs to be able to resolve it's own hostname. Cue the handy-dandy hosts file.</p>
<p>Under Network -> Global Configuration -> Host name data …</p><p>I discovered a while ago that NFS requires DNS to function correctly: <a href="https://redmine.ixsystems.com/issues/4983">https://redmine.ixsystems.com/issues/4983</a></p>
<p>That's somewhat annoying, because when your DNS server goes down (and your backups are stored on your FreeNAS server and accessed over NFS), is precisely the time when you really want your backups to be accessible.</p>
<p>However, turns out it doesn't <em>aaaaactuallyyyyy</em> need DNS... it needs <strong>name resolution</strong>. Specifically, FreeNAS just needs to be able to resolve it's own hostname. Cue the handy-dandy hosts file.</p>
<p>Under Network -> Global Configuration -> Host name data base, add your details:</p>
<div class="highlight"><pre><span></span><code><span class="err">192.168.88.5 backupserver backupserver.local backupserver.ad.mydomain.com</span>
</code></pre></div>
<p>If you have a secondary IP address, duplicate the above line and replace the IP as appropriate.</p>
<p>Obviously, replace the hostname and your internal domain name with whatever you use. However, be aware that the .local FQDN is <strong>actually</strong> required, even if you use a different domain name.</p>Flashing a Samsung S5 G900I back to stock2017-12-19T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2017-12-19:/flashing-a-samsung-s5-g900i-back-to-stock.html<p>I got a second-hand Samsung Galaxy S5 for my mum yesterday (a G900I model, from Telstra), and I spent some time getting it ready.</p>
<p>Firstly, I <a href="https://www.sammobile.com/firmwares/galaxy-s5/SM-G900I/">downloaded</a> the most-recent Telstra firmware image. At time of writing, that's G900IDVU1CQJ2. Telstra appears to be the only carrier still releasing stock firmware for this phone, so I downloaded the Telstra version even though we're connecting to Spark New Zealand. This means the phone will at least be running the most up-to-date baseband and modem firmware.</p>
<p>Note - if you try this, and find that …</p><p>I got a second-hand Samsung Galaxy S5 for my mum yesterday (a G900I model, from Telstra), and I spent some time getting it ready.</p>
<p>Firstly, I <a href="https://www.sammobile.com/firmwares/galaxy-s5/SM-G900I/">downloaded</a> the most-recent Telstra firmware image. At time of writing, that's G900IDVU1CQJ2. Telstra appears to be the only carrier still releasing stock firmware for this phone, so I downloaded the Telstra version even though we're connecting to Spark New Zealand. This means the phone will at least be running the most up-to-date baseband and modem firmware.</p>
<p>Note - if you try this, and find that the recent (international) version doesn't work properly with your local carriers, download the older (local) package, and flash the modem.bin and the NON-HLOS.bin packages from the local one instead.</p>
<p>Flashing the new firmware required a little thinking. I'm 99% sure that I did this the hard way, but basically:</p>
<ul>
<li>Download the newest version of <a href="https://github.com/Benjamin-Dobell/Heimdall">Heimdall from Github</a></li>
<li>Back last year I had <a href="https://www.ericlight.com/compiling-heimdall-without-installing-qt.html">a post</a> that mentioned editing CMakeLists.txt - ignore that now.</li>
<li>Build the software (assuming you extracted the zip instead of using <code>git clone</code>), with:<div class="highlight"><pre><span></span><code><span class="err">cd Heimdall-master</span>
<span class="err">mkdir build</span>
<span class="err">cd build</span>
<span class="err">cmake -DDISABLE_FRONTEND=ON -DCMAKE_BUILD_TYPE=Release .. </span>
<span class="err">make</span>
</code></pre></div>
</li>
</ul>
<p>Once I'd built Heimdall, I unzipped the firmware into a convenient place, and I examined the PIT file from the phone:</p>
<div class="highlight"><pre><span></span><code><span class="err">./heimdall print-pit</span>
</code></pre></div>
<p>This descripts the partition table on the phone. In particular, it tells you which files in your firmware package should be uploaded to which partitions. I ended up with the following Heimdall flash line:</p>
<div class="highlight"><pre><span></span><code><span class="err">./heimdall flash --APNHLOS NON-HLOS.bin --MODEM modem.bin --SBL1 sbl1.mbn --DBI sdi.mbn --ABOOT aboot.mbn --RPM rpm.mbn --TZ tz.mbn --BOOT boot.img --RECOVERY recovery.img --SYSTEM system.img.ext4 --CACHE cache.img.ext4 --HIDDEN hidden.img.ext4</span>
</code></pre></div>
<p>I know I could have only flashed the modem.bin and NON-HLOS.bin files, but I'm not sure what I would have missed by skipping all the other partitions.</p>
<p>After the phone was flashed up to the current Stock firmware, I made sure it booted correctly, and then went ahead and converted the phone to my beloved <a href="https://www.lineageos.org">LineageOS</a>, happy in the knowledge that all the "other bits" of the firmware were all updated.</p>Making MindTouch's Dekiwiki work on Debian Stretch2017-09-17T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2017-09-17:/making-mindtouchs-dekiwiki-work-on-debian-stretch.html<p>We had accumulated a certain amount of technical debt, due to a Wiki solution that was selected a few years ago: Dekiwiki, by MindTouch. Unfortunately a few months after implementation, MindTouch Core (which Dekiwiki builds on) was <a href="https://mindtouch.com/resources/mindtouch-core-and-platform-this-is-the-end-beautiful-friend">well-and-truly deprecated</a> back in 2013.</p>
<p>It all happened before my time, but it seems as if Dekiwiki came as a pre-built VMware Appliance, based on Debian Etch (<a href="https://en.wikipedia.org/wiki/Debian_version_history#Debian_4.0_.28Etch.29">Debian 4.0; released in 2007</a>). After giving our Dekiwiki environment some serious side-eye for a while, I finally decided to get my hands dirty and …</p><p>We had accumulated a certain amount of technical debt, due to a Wiki solution that was selected a few years ago: Dekiwiki, by MindTouch. Unfortunately a few months after implementation, MindTouch Core (which Dekiwiki builds on) was <a href="https://mindtouch.com/resources/mindtouch-core-and-platform-this-is-the-end-beautiful-friend">well-and-truly deprecated</a> back in 2013.</p>
<p>It all happened before my time, but it seems as if Dekiwiki came as a pre-built VMware Appliance, based on Debian Etch (<a href="https://en.wikipedia.org/wiki/Debian_version_history#Debian_4.0_.28Etch.29">Debian 4.0; released in 2007</a>). After giving our Dekiwiki environment some serious side-eye for a while, I finally decided to get my hands dirty and try to upgrade it.</p>
<p>Jedd, over at Jeddi.org, wrote <a href="https://jeddi.org/b/resurrecting-mindtouch-dekiwiki.html#resurrecting-mindtouch-dekiwiki">a really helpful post back in 2015</a> about his experiences updating the ageing version of Debian that the VM is based on. The whole Dekiwiki image is held together by sticky-tape, but that post is really helpful in getting Etch upgraded to Wheezy.</p>
<p>Here are a couple <strong>additional</strong> things I've had to do (please, please look at Jedd's post above - he covers a whole lot that I'm not covering here):</p>
<h2>Upgrading Etch -> Lenny:</h2>
<p>Follow <a href="https://jeddi.org/b/resurrecting-mindtouch-dekiwiki.html#resurrecting-mindtouch-dekiwiki">the guide at Jeddi.org</a> above to get to Lenny. I can't remember much failing for that upgrade step, but I remember something happened.</p>
<h2>From Lenny -> Squeeze:</h2>
<p><strong>DNS Breaks.</strong> You'll notice that SSH takes aaaages to log into, and other things will start being slow and complaining. </p>
<p>Resolve this by editing the 'hosts' line in /etc/nsswitch.conf:</p>
<p><code>hosts: files dns</code></p>
<p>Originally this reads <code>hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4</code></p>
<p>Note I'm not actually sure this happened between Lenny and Squeeze; it may have been from Squeeze to Wheezy. *shrug*</p>
<h2>From Squeeze -> Wheezy:</h2>
<p><strong>MySQL breaks.</strong> When visiting the wiki, you'll be informed that it couldn't access the backend, and that the API might be warming up. However, you'll notice that the MySQL service fails to start. When you run 'mysqld' from command line, you'll see it's missing a folder. </p>
<p>Resolve this by running <code>mkdir /var/lib/mysql-files ; chown mysql:mysql /var/lib/mysql-files</code></p>
<h2>From Wheezy -> Jessie (upgrade-only):</h2>
<p><strong>Apache breaks.</strong> You'll notice Apache starts serving just the contents of /var/www. This is because the Apache config file now looks for *.conf in /etc/apache2/sites-enabled; of course, the dekiwiki config file doesn't have the .conf ending.</p>
<p>Resolve this by running <code>mv /etc/apache2/sites-enabled/dekiwiki /etc/apache2/sites-enabled/dekiwiki.conf</code></p>
<h2>From Wheezy -> Jessie (dist-upgrade):</h2>
<p><strong>Mono breaks.</strong> If you upgrade mono, Dekiwiki will fall back into unlicensed mode. The licensing engine will no longer be able to interpret license files correctly. You'll see the error "Server license validation failed. The license signature is not valid."</p>
<p>Resolve this by holding back the mono packages before you run a dist-upgrade:</p>
<p><code>apt-mark hold libapache2-mod-mono libmono-2.0-1 libmono-2.0-dev libmono-accessibility2.0-cil libmono-accessibility4.0-cil libmono-bytefx0.7.6.2-cil libmono-c5-1.1-cil libmono-cairo2.0-cil libmono-cairo4.0-cil libmono-cecil-private-cil libmono-codecontracts4.0-cil libmono-compilerservices-symbolwriter4.0-cil libmono-corlib2.0-cil libmono-corlib4.0-cil libmono-cscompmgd8.0-cil libmono-csharp4.0-cil libmono-custommarshalers4.0-cil libmono-data-tds2.0-cil libmono-data-tds4.0-cil libmono-data2.0-cil libmono-db2-1.0-cil libmono-debugger-soft2.0-cil libmono-debugger-soft4.0-cil libmono-dev libmono-firebirdsql1.7-cil libmono-getoptions2.0-cil libmono-http4.0-cil libmono-i18n-cjk4.0-cil libmono-i18n-mideast4.0-cil libmono-i18n-other4.0-cil libmono-i18n-rare4.0-cil libmono-i18n-west2.0-cil libmono-i18n-west4.0-cil libmono-i18n2.0-cil libmono-i18n4.0-all libmono-i18n4.0-cil libmono-ldap2.0-cil libmono-ldap4.0-cil libmono-management2.0-cil libmono-management4.0-cil libmono-messaging-rabbitmq2.0-cil libmono-messaging-rabbitmq4.0-cil libmono-messaging2.0-cil libmono-messaging4.0-cil libmono-microsoft-build-engine4.0-cil libmono-microsoft-build-framework4.0-cil libmono-microsoft-build-tasks-v4.0-4.0-cil libmono-microsoft-build-utilities-v4.0-4.0-cil libmono-microsoft-build2.0-cil libmono-microsoft-csharp4.0-cil libmono-microsoft-visualc10.0-cil libmono-microsoft-web-infrastructure1.0-cil libmono-microsoft8.0-cil libmono-npgsql2.0-cil libmono-npgsql4.0-cil libmono-opensystem-c4.0-cil libmono-oracle2.0-cil libmono-oracle4.0-cil libmono-peapi2.0-cil libmono-peapi4.0-cil libmono-posix2.0-cil libmono-posix4.0-cil libmono-rabbitmq2.0-cil libmono-rabbitmq4.0-cil libmono-relaxng2.0-cil libmono-relaxng4.0-cil libmono-security2.0-cil libmono-security4.0-cil libmono-sharpzip2.6-cil libmono-sharpzip2.84-cil libmono-sharpzip4.84-cil libmono-simd2.0-cil libmono-simd4.0-cil libmono-sqlite2.0-cil libmono-sqlite4.0-cil libmono-system-componentmodel-composition4.0-cil libmono-system-componentmodel-dataannotations4.0-cil libmono-system-configuration-install4.0-cil libmono-system-configuration4.0-cil libmono-system-core4.0-cil libmono-system-data-datasetextensions4.0-cil libmono-system-data-linq2.0-cil libmono-system-data-linq4.0-cil libmono-system-data-services-client4.0-cil libmono-system-data-services4.0-cil libmono-system-data2.0-cil libmono-system-data4.0-cil libmono-system-design4.0-cil libmono-system-drawing-design4.0-cil libmono-system-drawing4.0-cil libmono-system-dynamic4.0-cil libmono-system-enterpriseservices4.0-cil libmono-system-identitymodel-selectors4.0-cil libmono-system-identitymodel4.0-cil libmono-system-ldap2.0-cil libmono-system-ldap4.0-cil libmono-system-management4.0-cil libmono-system-messaging2.0-cil libmono-system-messaging4.0-cil libmono-system-net4.0-cil libmono-system-numerics4.0-cil libmono-system-runtime-caching4.0-cil libmono-system-runtime-durableinstancing4.0-cil libmono-system-runtime-serialization-formatters-soap4.0-cil libmono-system-runtime-serialization4.0-cil libmono-system-runtime2.0-cil libmono-system-runtime4.0-cil libmono-system-security4.0-cil libmono-system-servicemodel-discovery4.0-cil libmono-system-servicemodel-routing4.0-cil libmono-system-servicemodel-web4.0-cil libmono-system-servicemodel4.0-cil libmono-system-serviceprocess4.0-cil libmono-system-transactions4.0-cil libmono-system-web-abstractions4.0-cil libmono-system-web-applicationservices4.0-cil libmono-system-web-dynamicdata4.0-cil libmono-system-web-extensions-design4.0-cil libmono-system-web-extensions4.0-cil libmono-system-web-mvc1.0-cil libmono-system-web-mvc2.0-cil libmono-system-web-routing4.0-cil libmono-system-web-services4.0-cil libmono-system-web2.0-cil libmono-system-web4.0-cil libmono-system-windows-forms-datavisualization4.0-cil libmono-system-windows-forms4.0-cil libmono-system-xaml4.0-cil libmono-system-xml-linq4.0-cil libmono-system-xml4.0-cil libmono-system2.0-cil libmono-system4.0-cil libmono-tasklets2.0-cil libmono-tasklets4.0-cil libmono-wcf3.0-cil libmono-web4.0-cil libmono-webbrowser2.0-cil libmono-webbrowser4.0-cil libmono-webmatrix-data4.0-cil libmono-windowsbase3.0-cil libmono-windowsbase4.0-cil libmono-winforms2.0-cil libmono0 libmono2.0-cil mono-2.0-devel mono-2.0-gac mono-4.0-gac mono-apache-server2 mono-common mono-csharp-shell mono-dmcs mono-gac mono-gmcs mono-mcs mono-runtime mono-utils mono-xbuild</code></p>
<p><strong>Note:</strong> Some of these can certainly be unheld. I haven't yet gone through and identified exactly which component is breaking on upgrade. If you put in the effort to determine the culprit, please let me know.</p>
<p>That's all! You should now have Dekiwiki running on Debian Stretch! I'm planning to upgrade it to Debian Buster in the next week or two.</p>Compiling Heimdall without installing Qt2017-09-13T00:00:00+12:002017-12-19T00:00:00+13:00Eric Lighttag:www.ericlight.com,2017-09-13:/compiling-heimdall-without-installing-qt.html<p>During my recent <a href="https://www.ericlight.com/when-encryption-attacks.html">Wrecked-phone Saga</a>, I had some trouble flashing my firmware. My phone was broken at the time, so I couldn't enable ADB Debugging - therefore adb wasn't an option. OEM Bootlock was on, so fastboot wasn't an option. My Recovery bootloader was also broken. I thought my phone was bricked.</p>
<p>That's until I remembered Heimdall.</p>
<p><a href="http://glassechidna.com.au/heimdall/">Heimdall</a> is specifically a tool for working with the partitions on Samsung phones - other visitors need not apply. It works a treat for my Samsung Galaxy S5 (kltedv) though.</p>
<p>Heimdall, however, is <strong>old</strong>. The …</p><p>During my recent <a href="https://www.ericlight.com/when-encryption-attacks.html">Wrecked-phone Saga</a>, I had some trouble flashing my firmware. My phone was broken at the time, so I couldn't enable ADB Debugging - therefore adb wasn't an option. OEM Bootlock was on, so fastboot wasn't an option. My Recovery bootloader was also broken. I thought my phone was bricked.</p>
<p>That's until I remembered Heimdall.</p>
<p><a href="http://glassechidna.com.au/heimdall/">Heimdall</a> is specifically a tool for working with the partitions on Samsung phones - other visitors need not apply. It works a treat for my Samsung Galaxy S5 (kltedv) though.</p>
<p>Heimdall, however, is <strong>old</strong>. The version in the Debian Sid repository is 1.4.1, which <a href="http://metadata.ftp-master.debian.org/changelogs/main/h/heimdall-flash/heimdall-flash_1.4.1-2_changelog">dates back to 2015</a>. And when we have old versions, we also have incompatibilites! Such as Heimdall 1.4.1's <a href="https://github.com/Benjamin-Dobell/Heimdall/issues/209">incompatibility with newer versions of Samsung devices</a> ... such as my precious SGS5.</p>
<p>Happily, Heimdall is open source, so I was able to download and compile a new version that overcomes the problem. And that's how I found myself staring at the screen and looking at this:</p>
<p><img alt="Do I really need to install 55 packages to build this?" src="https://www.ericlight.com/images/yuck.png"></p>
<p><strong>That is Yuck.bat</strong></p>
<p>I really didn't want to install 55 packages just to build this. The majority of missing packages were required to build the GUI section of the tool, which I didn't want to use anyway. What if I could ... <em>build Heimdall without building the GUI??</em></p>
<p>And of course, that's the title of this article, so here's how to do it!</p>
<p><strong>EDIT 2017-12-19: The stuff below is no longer necessary. For better instructions, have a look at my article about <a href="https://www.ericlight.com/flashing-a-samsung-s5-g900i-back-to-stock.html">flashing a Samsung G900I back to stock</a>.</strong></p>
<ol>
<li>
<p>Clone the git repository, with <code>git clone https://github.com/Benjamin-Dobell/Heimdall.git</code></p>
</li>
<li>
<p>Edit the CMakeLists.txt file: <code>nano Heimdall/CMakeLists.txt</code></p>
</li>
<li>
<p>Delete the last four lines of CMakeLists.txt:</p>
<div class="highlight"><pre><span></span><code><span class="nb">cmake_minimum_required</span><span class="p">(</span><span class="s">VERSION</span> <span class="s">2.8.4</span><span class="p">)</span>
<span class="nb">set</span><span class="p">(</span><span class="s">CMAKE_MODULE_PATH</span>
<span class="o">${</span><span class="nv">CMAKE_SOURCE_DIR</span><span class="o">}</span><span class="s">/cmake</span>
<span class="o">${</span><span class="nv">CMAKE_MODULE_PATH</span><span class="o">}</span><span class="p">)</span>
<span class="nb">project</span><span class="p">(</span><span class="s">Heimdall</span><span class="p">)</span>
<span class="nb">set</span><span class="p">(</span><span class="s">CMAKE_RUNTIME_OUTPUT_DIRECTORY</span> <span class="o">${</span><span class="nv">CMAKE_BINARY_DIR</span><span class="o">}</span><span class="s">/bin</span><span class="p">)</span>
<span class="nb">option</span><span class="p">(</span><span class="s">DISABLE_FRONTEND</span> <span class="s2">"Disable GUI frontend"</span> <span class="s">OFF</span><span class="p">)</span>
<span class="nb">add_subdirectory</span><span class="p">(</span><span class="s">libpit</span><span class="p">)</span>
<span class="nb">add_subdirectory</span><span class="p">(</span><span class="s">heimdall</span><span class="p">)</span>
</code></pre></div>
</li>
<li>
<p>You're done! Go ahead and build according to the instructions.</p>
</li>
</ol>When Encryption Attacks!2017-09-12T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2017-09-12:/when-encryption-attacks.html<p>So... I wrecked my phone last night. :-(</p>
<p>Android's phone encryption feature has been around for aaaages, so I was confident when I started the encryption process last night. Unfortunately, something went wrong, and last night I discovered that everything was toast.</p>
<p>After a bit of digging, I found someone else with <a href="https://forum.xda-developers.com/galaxy-s4-sprint/help/phone-encrypted-access-twrp-t3587534"><strong>exactly</strong> the same problem</a>! </p>
<blockquote>
<p>"unable to boot into my phone as it sits at the boot screen. When I try to boot into TWRP, it asks for my password. [...] it appears to decrypt the partition and mount, but then …</p></blockquote><p>So... I wrecked my phone last night. :-(</p>
<p>Android's phone encryption feature has been around for aaaages, so I was confident when I started the encryption process last night. Unfortunately, something went wrong, and last night I discovered that everything was toast.</p>
<p>After a bit of digging, I found someone else with <a href="https://forum.xda-developers.com/galaxy-s4-sprint/help/phone-encrypted-access-twrp-t3587534"><strong>exactly</strong> the same problem</a>! </p>
<blockquote>
<p>"unable to boot into my phone as it sits at the boot screen. When I try to boot into TWRP, it asks for my password. [...] it appears to decrypt the partition and mount, but then while loading, TWRP shows a continuous stream of:</p>
<p><span style="color:red">E:Error parsing XML file</span></p>
<p>errors until it just restarts."</p>
</blockquote>
<p>Unfortunately, nobody responded to my own personal <a href="https://xkcd.com/979/">denvercoder9</a>.</p>
<p>Long story short, I lost everything. But for a while, I thought my <em>entire phone</em> was bricked. The phone wasn't accessible in either Recovery mode (due to the XML parsing catastrophe) <strong>or</strong> Download mode - it wasn't accessible either via adb or via fastboot.</p>
<p>Eventually my mate <a href="https://keybase.io/rendition">@rendition</a> pointed out that I could just boot into Recovery, then cancel the decryption step and wipe my phone from there. That allowed me to start again from a clean slate.</p>
<p>And I encrypted my phone right away, with no trouble at all!</p>Firmware update on an APC AP9630 NMC22017-09-02T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2017-09-02:/firmware-update-on-an-apc-ap9630-nmc2.html<p>I've spent a little while working with the <a href="http://www.apc.com/shop/us/en/products/UPS-Network-Management-Card-2/P-AP9630">APC Network Management Cards</a> now, and firmware updates are a total pain.</p>
<p>The biggest issue is that the UPS power outlets need to be <strong>powered off</strong> in order to flash the firmware, otherwise there's a terrifyingly-high chance that the NMC (a ~$700 card) will completely shit itself, and die permanently. Aside from that, I've never managed to get updates working properly from the web interface.</p>
<p>Fortunately, the card is hot-pluggable, so if you have a spare UPS hanging around, you can unplug …</p><p>I've spent a little while working with the <a href="http://www.apc.com/shop/us/en/products/UPS-Network-Management-Card-2/P-AP9630">APC Network Management Cards</a> now, and firmware updates are a total pain.</p>
<p>The biggest issue is that the UPS power outlets need to be <strong>powered off</strong> in order to flash the firmware, otherwise there's a terrifyingly-high chance that the NMC (a ~$700 card) will completely shit itself, and die permanently. Aside from that, I've never managed to get updates working properly from the web interface.</p>
<p>Fortunately, the card is hot-pluggable, so if you have a spare UPS hanging around, you can unplug the NMC from each UPS in your fleet, throw it into your spare, and flash the firmware from there. Fast, easy, and simple... as long as you have that all-important spare.</p>
<h2>Download the Firmware</h2>
<p>First, download the appropriate firmware for your device. At time of writing, the link for the SmartUPS 6.5.0 NMC firmware <a href="http://www.apc.com/us/en/tools/download/download.cfm?sw_sku=SFSUMX650&software_id=MFOI-APKQJS&family=98&part_num=AP9630&swfam=&tsk=">can be found here</a>, but if it's been a while you should find a new version at <a href="http://www.apc.com/us/en/tools/download/">http://www.apc.com/us/en/tools/download/</a>.</p>
<p>It comes down as an EXE file, but use 7-zip to extract the archive somewhere convenient. You only need the three .bin files:</p>
<ul>
<li>apc_hw05_bootmon_108.bin</li>
<li>apc_hw05_aos_650.bin</li>
<li>apc_hw05_sumx_650.bin</li>
</ul>
<h2>Flashing the Firmware</h2>
<p>Flashing the actual firmware is easy, but you do need to be careful of the order. The bootmon package goes first, then the AOS package, and then the sumx package.</p>
<p><strong>Be aware: the NMC will reboot immediately after each file is uploaded. As a result, you need to reconnect after each upload, and reissue the BIN command.</strong></p>
<p>Make sure you know the username and password (default credentials are apc/apc), and that the FTP server is enabled. Then, go ahead and ftp to the NMC on it's IP address.</p>
<div class="highlight"><pre><span></span><code>$ ftp
ftp> open x.x.x.x
Connected to x.x.x.x.
Name <span class="o">(</span>eric<span class="o">)</span>: apc
Password: apc
<span class="m">230</span> Login successful.
Remote system <span class="nb">type</span> is UNIX.
Using text mode to transfer files.
ftp> bin
Using binary mode to transfer files.
</code></pre></div>
<p>Make sure you send the 'bin' command. I also use the hash command so I can watch the transfer status, but it's unnecessary.</p>
<p>Once you've connected, go ahead and upload the bootmon file:</p>
<div class="highlight"><pre><span></span><code><span class="err">ftp> put apc_hw05_bootmon_108.bin</span>
<span class="err">ftp> close</span>
</code></pre></div>
<p>It'll only take a few seconds to upload the file, and you won't see any notification from the FTP server. But if you're paying attention to the card itself, you'll see the NMC network connection go down, and then start flashing. This is the NMC installing the new firmware package.</p>
<p>Once the connection is up again, your FTP session will be broken. Go ahead and reconnect; remember to reissue the BIN command:</p>
<div class="highlight"><pre><span></span><code><span class="err">ftp> put apc_hw05_bootmon_108.bin</span>
<span class="err">ftp> close</span>
<span class="err"><...snip...></span>
<span class="err">ftp> open x.x.x.x</span>
<span class="err"><...snip...></span>
<span class="err">ftp> bin</span>
<span class="err">Using binary mode to transfer files.</span>
</code></pre></div>
<p>Now upload the AOS file. When the NMC reboots again, go ahead and repeat the cycle to upload the sumx file.</p>
<p>Once the NMC reboots for the third time, you should be done!</p>
<h2>Thanks</h2>
<p>Thanks to Angela from APC - she's been around for years, and as far as I can see she's <em>THE</em> leading customer support person for the entire NMC firmware suite. You can find her post on this process <a href="http://forums.apc.com/spaces/7/ups-management-devices-powerchute-software/forums/general/3183/firmware-upgrade-for-ap9631-which-order">here at the APC forums</a>.</p>Respecting Amavis' "Banned Extensions" setting2017-08-13T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2017-08-13:/respecting-amavis-banned-extensions-setting.html<p>I've been dabbling a little bit with <a href="http://www.iredmail.org">iRedMail</a>, mostly just to have a play with a mail server, but also to see what's involved in mail security. iRedMail is a package that <a href="http://www.iredmail.org/docs/used.components.html">pulls together</a> Postfix as an MTA, Dovecot as a POP3 & IMAP server, SOGo for ActiveSync, Roundcube for Webmail, SpamAssassin for spam protection, and ClamAV for virus scanning.</p>
<p>Okay I have <strong>no idea</strong> why I have to write this, but apparently it's a thing.</p>
<p>Amavis has a list of banned file extensions. In Debian, they live in <code>/etc/amavis …</code></p><p>I've been dabbling a little bit with <a href="http://www.iredmail.org">iRedMail</a>, mostly just to have a play with a mail server, but also to see what's involved in mail security. iRedMail is a package that <a href="http://www.iredmail.org/docs/used.components.html">pulls together</a> Postfix as an MTA, Dovecot as a POP3 & IMAP server, SOGo for ActiveSync, Roundcube for Webmail, SpamAssassin for spam protection, and ClamAV for virus scanning.</p>
<p>Okay I have <strong>no idea</strong> why I have to write this, but apparently it's a thing.</p>
<p>Amavis has a list of banned file extensions. In Debian, they live in <code>/etc/amavis/conf.d/20-debian_defaults</code>, and <code>/etc/amavis/conf.d/50-user</code>, and are set in the <code>$banned_filename_re</code> variable. THIS MAKES PERFECT SENSE.</p>
<p>But of course, there's always something that doesn't make sense, and that is the fact that there is a SQL backend (at least in the environment created by iRedMail), and settings in here take precedence over the Amavis config files somehow.</p>
<p>And even more bizarrely, there exists in this SQL environment, a policy setting entitled "<em><strong>banned_files_lover</strong></em>", which was set to "Y". I shit you not. My only hope is that this only defaults to "Y" for postmaster.</p>
<p>To fix this, you need to hop into the database, and update the appropriate column in the <code>policy</code> table:</p>
<div class="highlight"><pre><span></span><code><span class="err">$</span><span class="w"> </span><span class="n">mariadb</span><span class="w"></span>
<span class="n">MariaDB</span><span class="w"> </span><span class="o">[</span><span class="n">none</span><span class="o">]></span><span class="w"> </span><span class="err">\</span><span class="n">u</span><span class="w"> </span><span class="n">amavis</span><span class="w"></span>
<span class="n">MariaDB</span><span class="w"> </span><span class="o">[</span><span class="n">amavisd</span><span class="o">]></span><span class="w"> </span><span class="k">update</span><span class="w"> </span><span class="n">policy</span><span class="w"> </span><span class="k">set</span><span class="w"> </span><span class="n">banned_files_lover</span><span class="o">=</span><span class="ss">"N"</span><span class="p">;</span><span class="w"></span>
</code></pre></div>
<p>And now, Amavis will obey your file extension filters!</p>
<p>Thankfully, I found this information at <a href="http://www.iredmail.org/forum/topic13147-iredmail-support-amavisd-passed-but-setup-at-ddiscard.html">http://www.iredmail.org/forum/topic13147-iredmail-support-amavisd-passed-but-setup-at-ddiscard.html</a> -- I never would have found it otherwise!</p>Tuna Patties2017-08-13T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2017-08-13:/tuna-patties.html<p>What do you do when it's dinner time, and you haven't got any ingredients ready for the meal?</p>
<p>What if (perhaps as a result of being an ultralight hiker), you also have a huge surplus 500g sachet of tuna?</p>
<p>Tonight these particular stars aligned, and I ended up making these amazing Tuna Patties: <a href="http://allrecipes.com.au/recipe/15705/tuna-patties.aspx">http://allrecipes.com.au/recipe/15705/tuna-patties.aspx</a></p>
<p>I did tweak the recipe considerably, though:</p>
<h2>Ingredients:</h2>
<ul>
<li>2-3 large potatoes, peeled and cubed for mashing</li>
<li>Optionally, swap one of the potatoes for a kumara or some pumpkin</li>
<li>500g …</li></ul><p>What do you do when it's dinner time, and you haven't got any ingredients ready for the meal?</p>
<p>What if (perhaps as a result of being an ultralight hiker), you also have a huge surplus 500g sachet of tuna?</p>
<p>Tonight these particular stars aligned, and I ended up making these amazing Tuna Patties: <a href="http://allrecipes.com.au/recipe/15705/tuna-patties.aspx">http://allrecipes.com.au/recipe/15705/tuna-patties.aspx</a></p>
<p>I did tweak the recipe considerably, though:</p>
<h2>Ingredients:</h2>
<ul>
<li>2-3 large potatoes, peeled and cubed for mashing</li>
<li>Optionally, swap one of the potatoes for a kumara or some pumpkin</li>
<li>500g tuna flakes</li>
<li>2 carrots, grated and excess juice dabbed out with a paper towel</li>
<li>A goodly handful of frozen chopped spinach</li>
<li>1 onion, cubed</li>
<li>3 garlic cloves, chopped</li>
<li>1/8th tsp cayenne pepper</li>
<li>1/2 tsp basil</li>
<li>1/2 tsp oregano</li>
<li>1/2 tsp sage</li>
<li>1 tsp veggie stock powder</li>
<li>2 eggs</li>
<li>2 tbsp mustard</li>
</ul>
<h2>Method:</h2>
<ul>
<li>Boil the potatoes in salted water until cooked.</li>
<li>In another pan, fry the onions for 2 minutes, then add garlic. </li>
<li>Fry until the onions start to brown, then add herbs, spices, and stock powder.</li>
<li>Continue to fry for another minute, then remove from heat and let cool.</li>
<li>When the potatoes are cooked, tip out <strong>all</strong> the water, and allow remaning water to evaporate.</li>
<li>Mash the potatoes - they'll seem unpleasantly dry, but that's OK.</li>
<li>Mix the carrots, mashed potatoes, fried onion and garlic, all together in a bowl.</li>
<li>In another bowl, mix together the tuna, the eggs, and the mustard.</li>
<li>Now combine everything together, and give it a good mix.</li>
<li>Form the mixture into patties and fry in a lightly oiled pan.</li>
</ul>
<p>In retrospect, this recipe seems really difficult, but it was actually quite straightforward, and it was totally delicious. Definitely good with a bit of mayo on the patties. Yummo!</p>Making Amavis work with ESET Antivirus2017-08-12T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2017-08-12:/making-amavis-work-with-eset-antivirus.html<p>I've been dabbling a little bit with <a href="http://www.iredmail.org">iRedMail</a>, mostly just to have a play with a mail server, but also to see what's involved in mail security. iRedMail is a package that <a href="http://www.iredmail.org/docs/used.components.html">pulls together</a> Postfix as an MTA, Dovecot as a POP3 & IMAP server, SOGo for ActiveSync, Roundcube for Webmail, SpamAssassin for spam protection, and ClamAV for virus scanning.</p>
<p>But of course, ClamAV has <a href="https://www.av-test.org/en/news/news-single-view/linux-16-security-packages-against-windows-and-linux-malware-put-to-the-test/">shown disappointing performance</a>, and it would be really nice to use something more... commercially suitable.</p>
<p>To tie together mail receipt and scanning, iRedMail uses <a href="https://www.ijs.si/software/amavisd/">Amavis</a> (strictly …</p><p>I've been dabbling a little bit with <a href="http://www.iredmail.org">iRedMail</a>, mostly just to have a play with a mail server, but also to see what's involved in mail security. iRedMail is a package that <a href="http://www.iredmail.org/docs/used.components.html">pulls together</a> Postfix as an MTA, Dovecot as a POP3 & IMAP server, SOGo for ActiveSync, Roundcube for Webmail, SpamAssassin for spam protection, and ClamAV for virus scanning.</p>
<p>But of course, ClamAV has <a href="https://www.av-test.org/en/news/news-single-view/linux-16-security-packages-against-windows-and-linux-malware-put-to-the-test/">shown disappointing performance</a>, and it would be really nice to use something more... commercially suitable.</p>
<p>To tie together mail receipt and scanning, iRedMail uses <a href="https://www.ijs.si/software/amavisd/">Amavis</a> (strictly speaking, 'amavisd-new'). Amavis uses ClamAV by default, but it comes with a bunch of <a href="https://www.apt-browse.org/browse/ubuntu/trusty/main/all/amavisd-new/1:2.7.1-2ubuntu3/file/etc/amavis/conf.d/15-av_scanners">configuration blocks</a> to bring together other antivirus applications.</p>
<p>But although amavisd-new is stable and still maintained, some parts of it are really old. In particular, many of these av-scanner config blocks are... uhh... "deprecated". There's one particular entry for ESET that is dated 2002 - things have changed a lot in the last fifteen years. *shudder*</p>
<p>So, with the help of <a href="https://www.akadia.com/download/documents/amavisd.conf.txt">some documentation</a>, I managed to piece together a code block that works:</p>
<div class="highlight"><pre><span></span><code><span class="err">['ESET File Security for Linux',</span>
<span class="err"> ['/opt/eset/esets/sbin/esets_scan','esets_scan'],</span>
<span class="err"> '--subdir --unsafe --unwanted --clean-mode=strict {}',</span>
<span class="err"> [0,10,100],[1,50],</span>
<span class="err"> qr/threat="([^"]+)"/m</span>
<span class="err">],</span>
</code></pre></div>
<p>That would be the end of the story, except I also had to hunt around to find out the right place to put my beautiful codeblock into. It turns out that Debian's Amavis config structure is quite different to the CentOS config that is most-frequently mentioned in the iRedMail forums. I spent a lot of time playing with <code>/etc/amavis/conf.d/15-av_scanners</code>, and nothing seemed to work. Eventually I found out that Debian features a <code>/etc/amavis/conf.d/50-users</code> file that overwrites the settings from <code>15-av_scanners</code>. Finally I had progress!</p>
<p>Somewhere around line 154 in <code>/etc/amavis/conf.d/50-users</code>, you'll find an <code>@av_scanners</code> codeblock. I deleted the ClamAV section in there, and replaced it with the ESET codeblock above. I left the ClamAV settings in the <code>@av_scanners_backup</code> section, because Amavis will fall back to that if ESET fails.</p>
<p>That seems to be all! At least, it works with the <a href="http://www.eicar.org/">EICAR anti-malware test file</a>.</p>RingZer0team CTF - Challenges 86, 87, and 882017-07-13T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2017-07-13:/ringzer0team-ctf-challenges-86-87-and-88.html<p>There are a bunch of fantastic Capture The Flag security challenges on <a href="https://www.ringzer0team.com">RingZer0Team.com</a>. I've been working through some of these for a wee while now, and with the <a href="https://www.cybersecuritychallenge.org.nz/">New Zealand Cyber Security Challenge</a> coming up again soon, I thought I'd get back into some of them.</p>
<p>Challenge 86 ("1/3 Do not waste the environment", under the Forsensic Challenges) is one of a series of challenges where you need to dig through some provided data to find the flag.</p>
<p>I started by downloading the 'forensic bundle', which was just …</p><p>There are a bunch of fantastic Capture The Flag security challenges on <a href="https://www.ringzer0team.com">RingZer0Team.com</a>. I've been working through some of these for a wee while now, and with the <a href="https://www.cybersecuritychallenge.org.nz/">New Zealand Cyber Security Challenge</a> coming up again soon, I thought I'd get back into some of them.</p>
<p>Challenge 86 ("1/3 Do not waste the environment", under the Forsensic Challenges) is one of a series of challenges where you need to dig through some provided data to find the flag.</p>
<p>I started by downloading the 'forensic bundle', which was just a large zip file. The first challenge was to figure out the contents of that zip file. The file name was just a jumble of characters, and there was no extension. Running <code>file</code> on it just returned the file type "Data"... not very enlightening, but <code>head</code> uncovered the string "VBOX" in the file... okay, it's VirtualBox file.</p>
<p>Because I didn't have Virtualbox installed, I spent a bit of time digging through the actual Vbox file itself, trying to see if there's a flag already in there. I used <code>strings | egrep -i flag-....</code>, to try to find any flags embedded in the file itself. I didn't find any flags, but I did discover that the computer name itself is "FLAG-PC". Very clever. :-|</p>
<h3>Update, many hours later:</h3>
<p>Okay this totally cooked my bacon. After hours of playing with VirtualBox and playing with files, I finally gave up and Googled the name of the downloaded file.</p>
<p>Turns out I was <em>REALLY</em> close. The flag IS embedded in the actual file itself, but the format is different for the first time. The correct grep string would have been <code>egrep -i '.?f.?l.?a.?g.?-'</code>.</p>
<p>Real frustrated by how close I was, I'll have to expand my searches in the future. Hat-tip to <a href="https://twitter.com/professormahi">@professormahi</a> and his <a href="https://github.com/professormahi/CTF/tree/master/ringzer0team/Forensics/1-3%20Do%20not%20waste%20the%20enviroment">GitHub</a> page.</p>
<p>Once I understood that, I also discovered the flag for challenge 87 ("2/3 Did you see my desktop?"), in the same manner.</p>
<p>I haven't managed to get the flag for Challenge 88 ("3/3 Suspicious Account Password") yet, but I do know what it is. I can see (by grepping for "Visited") a bunch of visits to <a href="http://www.forensicswiki.org/wiki/Tools:Memory_Imaging">http://www.forensicswiki.org/wiki/Tools:Memory_Imaging</a>... this thing is a memory dump. That explains now why it doesn't work as a VirtualBox disk.</p>
<p>Next time I sit down here, I'll find visit Forensics Wiki, and start digging through the memory dump for the passwords.</p>
<h3>Update two</h3>
<p>I decided not to put this up as a separate post, because once I knew what I was looking at, it was pretty easy. Again though, I relied on @professormahi's work - but now thanks to him I have a little bit of experience with <a href="https://www.volatilityfoundation.org/">Volatility</a>!</p>
<p>First, we get Volatility to scan the image and see what it's dealing with:</p>
<div class="highlight"><pre><span></span><code>$ volatility -f vm.vmdk imageinfo
Volatility Foundation Volatility Framework <span class="m">2</span>.6
INFO : volatility.debug : Determining profile based on KDBG search...
Suggested Profile<span class="o">(</span>s<span class="o">)</span> : Win7SP1x86_23418, Win7SP0x86, Win7SP1x86
AS Layer1 : IA32PagedMemory <span class="o">(</span>Kernel AS<span class="o">)</span>
AS Layer2 : FileAddressSpace <span class="o">(</span>/home/eric/Downloads/86/vm.vmdk<span class="o">)</span>
PAE <span class="nb">type</span> : No PAE
DTB : 0x185000L
KDBG : 0x82920be8L
Number of Processors : <span class="m">1</span>
Image Type <span class="o">(</span>Service Pack<span class="o">)</span> : <span class="m">0</span>
KPCR <span class="k">for</span> CPU <span class="m">0</span> : 0x82921c00L
KUSER_SHARED_DATA : 0xffdf0000L
Image date and <span class="nb">time</span> : <span class="m">2014</span>-03-09 <span class="m">20</span>:57:55 UTC+0000
Image <span class="nb">local</span> date and <span class="nb">time</span> : <span class="m">2014</span>-03-09 <span class="m">13</span>:57:55 -0700
</code></pre></div>
<p>Now, knowing the profile that we need to use, we can use it to just... dump the password table:</p>
<div class="highlight"><pre><span></span><code>$ volatility -f vm.vmdk --profile Win7SP1x86 hashdump
Volatility Foundation Volatility Framework <span class="m">2</span>.6
Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
flag:1000:aad3b435b51404eeaad3b435b51404ee:3008c87294511142799dca1191e69a0f:::
</code></pre></div>
<p>And then, we grab that NTLM hash and pop it into an online NTLM decryptor service, and we're away!</p>Staying Secure in Business2017-06-28T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2017-06-28:/staying-secure-in-business.html<p>A friend asked a question today on Facebook. I started writing a reply, and it turned into a 700-word essay. Hate it when that happens...</p>
<p>The question was: </p>
<h4><em>"If large multi-international companies are getting hacked in Europe who have millions if not billions of $$ and capacity to protect their IT systems - how can small/micro businesses protect their IT platforms and systems?"</em></h4>
<p>Firstly - nobody is safe from an APT ("Advanced Persistent Threat"). The recent <a href="https://twitter.com/search?q=NotPetya">NotPetya</a> outbreak was an APT - malicious actors hacked a Ukrainian firm that produced accounting software, and …</p><p>A friend asked a question today on Facebook. I started writing a reply, and it turned into a 700-word essay. Hate it when that happens...</p>
<p>The question was: </p>
<h4><em>"If large multi-international companies are getting hacked in Europe who have millions if not billions of $$ and capacity to protect their IT systems - how can small/micro businesses protect their IT platforms and systems?"</em></h4>
<p>Firstly - nobody is safe from an APT ("Advanced Persistent Threat"). The recent <a href="https://twitter.com/search?q=NotPetya">NotPetya</a> outbreak was an APT - malicious actors hacked a Ukrainian firm that produced accounting software, and <a href="https://medium.com/@thegrugq/pnyetya-yet-another-ransomware-outbreak-59afd1ee89d4">used their software's update facility</a> to literally deliver malicious code specifically to the users of this particular software package ("M.E. Doc"). Nothing's keeping folks safe from that level of sophistication.</p>
<p>However, the exploit by which NotPetya <em>spreads</em> was <a href="https://technet.microsoft.com/en-us/library/security/ms17-010.aspx">actually patched by Microsoft</a> in <strong>March</strong>. If people had updated their internet-connected devices, this virus would have been limited to only users of M.E. Doc.</p>
<p>Aside from that though, there's actually a disappointingly simple answer to this. Security is actually relatively within reach, if we all follow these simple steps:</p>
<h3>1) Update. Everything. At every opportunity.</h3>
<p>That includes Windows Updates, but also <a href="http://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=adobe+reader">Adobe Reader</a> (annoying!), <a href="http://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=java">Java</a> (double annoying!), <a href="https://twitter.com/taviso/status/860679110728622080">anti-virus engines</a>, etc. This is absolutely the top priority, and the cybersecurity industry has been trotting this line out for years, but people just don't. Because annoying.</p>
<p>Real life incident: June 22, 2017 - Honda falls prey to the WannaCry worm, 37 days after release (four months after the patch was released), due to poor patching hygiene. </p>
<p>See <a href="http://thehackernews.com/2017/06/honda-wannacry-attack.html">http://thehackernews.com/2017/06/honda-wannacry-attack.html</a></p>
<h3>2) Backup everything important.</h3>
<p>The more important it is, the more places you should keep it. You should have at least three copies of every important file. THIS IS ANNOYING, but if you don't do it, data loss will hit you. Something like <a href="https://www.crashplan.com">Crashplan</a> (a low-cost service that sends backups to the cloud), plus a regular (weekly?) copy to a read-only media (e.g. a DVD), should be enough for a small business.</p>
<p>Real life incident: Feb 1, 2017 - GitLabs suffers a major outage after data was accidentally deleted, followed by a sequence of discoveries that none of their five layers of backup or replication techniques “are working reliably or set up in the first place”. </p>
<p>See <a href="https://techcrunch.com/2017/02/01/gitlab-suffers-major-backup-failure-after-data-deletion-incident/">https://techcrunch.com/2017/02/01/gitlab-suffers-major-backup-failure-after-data-deletion-incident/</a></p>
<h3>3) Use next-generation anti-virus software.</h3>
<p>Many of the AV products these days include very clever ways of analysing the behaviour of unknown software, and literally just rolling back all the changes if the AV decides it's not trustworthy. <a href="https://www.webroot.com">Webroot</a> is a good example of this, at a very affordable price.</p>
<p>Real life incident: April 23, 2017 - the Adylkuzz virus started quietly spreading around the internet, and setting up Monero cryptocurrency mining operations on infected PC's. Because the payload wasn't destructive, it flew under the radar and was missed by many antiviruses for weeks. </p>
<p>See <a href="https://www.proofpoint.com/us/threat-insight/post/adylkuzz-cryptocurrency-mining-malware-spreading-for-weeks-via-eternalblue-doublepulsar">https://www.proofpoint.com/us/threat-insight/post/adylkuzz-cryptocurrency-mining-malware-spreading-for-weeks-via-eternalblue-doublepulsar</a></p>
<h3>4) Be alert, cautious, and sufficiently paranoid.</h3>
<p>The last - and hardest - step is to maintain a healthy sense of distrust; sometimes referred to as "<a href="https://pthree.org/2013/10/04/sufficient-paranoia/">sufficient paranoia</a>". When you receive an email, ask yourself: is this email in-character for this person? Is the spelling what I'd expect? Is it appropriate? Is it asking me to take an action (even if that action is just opening a file)? If so, is it expected, or is it out of the blue? If it's out of the blue, why? What's the story behind that?</p>
<p>Real life incident: Sept 30, 2011 - I received an email from a lady I'd once interviewed for a job. It was a distraught email saying she was stuck in Wales, had been mugged, lost all her money, and needed a brief loan until she got home. I wrote her an email (not a reply), telling her email had been hacked; lo and behold, I got a reply! "It's me... this is for real, i have checked with the consulate but there is nothing really working out, most important is i don't have enough money on please, please i need you to loan me some, i can pay you back once i get home."</p>
<p>I ended up finding her cellphone number and sending her a message - she was at home, safe and sound.</p>
<p>See <a href="https://blog.malwarebytes.com/cybercrime/2014/08/email-hijack-leads-to-i-was-robbed-send-me-money-scam/">https://blog.malwarebytes.com/cybercrime/2014/08/email-hijack-leads-to-i-was-robbed-send-me-money-scam/</a> -- this was exactly the wording I received.</p>
<h3>Geez, that was a long Facebook post Eric.</h3>
<p>It really was, and a few minutes afterwards, this tweet came to my attention:</p>
<p><a href="https://twitter.com/josephfcox/status/879982828418719744">https://twitter.com/josephfcox/status/879982828418719744</a></p>
<p>It's fun to laugh, but it's a good reminder that there's always going to be a weakness. You need to structure your business disaster recovery in a way that you can quickly and efficiently deal with a complete wipe-out like this.</p>
<h3>And we're done.</h3>
<p>So, to summarise this essay, you need to:</p>
<ul>
<li>Always install updates</li>
<li>Always take backups</li>
<li>Use AV software with full journaling and rollback capabilities</li>
<li>Practice sufficient paranoia</li>
</ul>
<p>With these four steps, you will be as safe as the biggest corporate. (roughly speaking)</p>RingZer0team CTF - Challenge 442017-06-24T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2017-06-24:/ringzer0team-ctf-challenge-44.html<p>There are a bunch of fantastic Capture The Flag security challenges on <a href="https://www.ringzer0team.com">RingZer0Team.com</a>. I've been working through some of these for a wee while now, and with the <a href="https://www.cybersecuritychallenge.org.nz/">New Zealand Cyber Security Challenge</a> coming up again soon, I thought I'd get back into some of them.</p>
<p>Challenge 56 ("Hey Chuck where is the flag?", under the Forensic Challenges) started by only offering a .pcap file. I downloaded Wireshark and had a quick dig. The packet capture consisted of a brief browse of a "Chuck Norris Facts" website.</p>
<p>After quickly …</p><p>There are a bunch of fantastic Capture The Flag security challenges on <a href="https://www.ringzer0team.com">RingZer0Team.com</a>. I've been working through some of these for a wee while now, and with the <a href="https://www.cybersecuritychallenge.org.nz/">New Zealand Cyber Security Challenge</a> coming up again soon, I thought I'd get back into some of them.</p>
<p>Challenge 56 ("Hey Chuck where is the flag?", under the Forensic Challenges) started by only offering a .pcap file. I downloaded Wireshark and had a quick dig. The packet capture consisted of a brief browse of a "Chuck Norris Facts" website.</p>
<p>After quickly flicking through the pcap itself looking for low-hanging fruit, I used File -> Export Objects -> HTTP. This takes all the HTTP traffic, recombines the packets into files, and saves them.</p>
<p>Once I'd done that, I opened up the files and had a quick flick through. I checked the images for metadata etc but didn't find anything. However I did fine a picture of Chuck Norris, appearing to urge the reader to keep searching files -- in French.</p>
<p>When I didn't find anything super-obvious in the image contents, I hopped into Bash and just ran <code>grep -i flag *</code>. It quickly returned the flag, stored in a php file!</p>
<p>Nice and easy hunt, great way to finish the day.</p>RingZer0team CTF - Challenge 652017-06-24T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2017-06-24:/ringzer0team-ctf-challenge-65.html<p>This is a continuation of my series on <a href="https://www.ringzer0team.com">RingZer0Team.com</a>. </p>
<p>Challenge 65 ("Hide my ass in my home", under the Forensic challenges) is a nice quick little forensic challenge. You get to download a .tar file, and do a bit of digging to uncover the flag.</p>
<p>This was a nice easy few minutes. After downloading the archive, I discovered a few files inside - including a <em>particularly groovy</em> electronica swing track, which I'm listening to again right now. Yeaaaaahhhhh.</p>
<p>Apart from a groovy mp3, the archive contains some dot-files such as …</p><p>This is a continuation of my series on <a href="https://www.ringzer0team.com">RingZer0Team.com</a>. </p>
<p>Challenge 65 ("Hide my ass in my home", under the Forensic challenges) is a nice quick little forensic challenge. You get to download a .tar file, and do a bit of digging to uncover the flag.</p>
<p>This was a nice easy few minutes. After downloading the archive, I discovered a few files inside - including a <em>particularly groovy</em> electronica swing track, which I'm listening to again right now. Yeaaaaahhhhh.</p>
<p>Apart from a groovy mp3, the archive contains some dot-files such as .bash_history, a .jpg picture, an index.html, and some other bits.</p>
<p>I found the Flag in one of the dot-files; specifically, it was inside a Vim swap file that seemed to be leftover from a power failure or similar.</p>WireGuard - Part Three (Troubleshooting)2017-06-12T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2017-06-12:/wireguard-part-three-troubleshooting.html<p>This is part of my <a href="https://www.ericlight.com/wireguard-part-one-installation.html">brief</a> <a href="https://www.ericlight.com/wireguard-part-two-vpn-routing.html">series</a> on <a href="https://wireguard.com/">WireGuard</a>. I'm pretty enamoured with WireGuard and the way it works, but there were a couple slightly curly bits that I needed to get my head around. This troubleshooting guide is a rough dump of the issues I had, and how I fixed them.</p>
<h2>Gotten Stuck?</h2>
<p>At this stage, there are actually a few ways that this can go wrong, even though we haven't done much. Think through all the bits:</p>
<ul>
<li>Installed WireGuard at both ends</li>
<li>Set up your NAT rule on …</li></ul><p>This is part of my <a href="https://www.ericlight.com/wireguard-part-one-installation.html">brief</a> <a href="https://www.ericlight.com/wireguard-part-two-vpn-routing.html">series</a> on <a href="https://wireguard.com/">WireGuard</a>. I'm pretty enamoured with WireGuard and the way it works, but there were a couple slightly curly bits that I needed to get my head around. This troubleshooting guide is a rough dump of the issues I had, and how I fixed them.</p>
<h2>Gotten Stuck?</h2>
<p>At this stage, there are actually a few ways that this can go wrong, even though we haven't done much. Think through all the bits:</p>
<ul>
<li>Installed WireGuard at both ends</li>
<li>Set up your NAT rule on the remote side</li>
<li>Created a private and public key on each side</li>
<li>Put each public key in the opposite side's [Peer] config</li>
<li>Put a suitable IP address on each side</li>
</ul>
<h2>Troubleshooting</h2>
<p>There are, actually, a myriad of ways this can fail:</p>
<ul>
<li>Broken routing on the client PC</li>
<li>Broken NAT on the remote router</li>
<li>Broken routing on the remote PC</li>
<li>Broken wg0 configuration on one side</li>
<li>Lack of TCP forwarding on the remote computer</li>
<li>Lack of Proxy ARP on the remote computer</li>
</ul>
<p>If you can't ping the remote server yet, don't panic. Run tcpdump to find out what you're missing.</p>
<ul>
<li>On the remote server: <code>tcpdump -i wg0</code></li>
<li>On your local machine: <code>ping -c1 10.20.40.1</code></li>
</ul>
<p>That will tell you whether your packets are reaching the remote server, or if they're not getting through the tunnel.</p>
<p>If they're not making it through the tunnel at all, you'll probably be seeing error messages in the ping. For example:</p>
<div class="highlight"><pre><span></span><code><span class="err">PING 10.20.10.1 (10.20.10.1) 56(84) bytes of data.</span>
<span class="err">From 10.20.40.2 icmp_seq=1 Destination Host Unreachable</span>
<span class="c">ping: sendmsg: Required key not available</span>
</code></pre></div>
<p>That's the error message I got when I set AllowedIPs too strictly. Because I was trying to ping something that was <strong>routable</strong>, but wasn't within the AllowedIPs range, there was no applicable key for the packet.</p>
<h2>Thanks</h2>
<p>Huge gratitude to <a href="https://www.zx2c4.com/">Jason Donenfeld</a> (aka zx2c4) for spending his time not only reading this post, but also for sending me some fantastic feedback! I'd made some bungles in my original post on this topic, and he vastly helped my understanding.</p>
<p>Also, huge gratitude to another Jason (<a href="https://keybase.io/rendition">@rendition</a>) who has helped me develop from a junior network admin into a ... 'moderate' network admin. I've learned more in the last year than I ever thought possible. He's taught me nearly everything I know about managed networking, reviewed this post for me, and is actually the guy who introduced me to WireGuard originally!</p>WireGuard - Part Two (VPN routing)2017-06-11T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2017-06-11:/wireguard-part-two-vpn-routing.html<p>This is a continuation of my brief series on the new <a href="https://wireguard.com/">WireGuard</a> VPN. <a href="https://www.ericlight.com/wireguard-part-one-installation.html">Part One</a> was about the simple building-blocks to get WireGuard working between two endpoints. Now that we've got a couple machines able to ping each other by IP address, we can carry on a bit deeper into the inter-LAN routing stuff.</p>
<p>Extending on from the IP addresses in Part One, instead of JUST connecting to the remote machine, I want to actually have access to everything <em>on the whole 10.20.0.0/16 network</em>; even the …</p><p>This is a continuation of my brief series on the new <a href="https://wireguard.com/">WireGuard</a> VPN. <a href="https://www.ericlight.com/wireguard-part-one-installation.html">Part One</a> was about the simple building-blocks to get WireGuard working between two endpoints. Now that we've got a couple machines able to ping each other by IP address, we can carry on a bit deeper into the inter-LAN routing stuff.</p>
<p>Extending on from the IP addresses in Part One, instead of JUST connecting to the remote machine, I want to actually have access to everything <em>on the whole 10.20.0.0/16 network</em>; even the non-WireGuard devices. I want it to be like I'm there on-site. The idea here is roughly:</p>
<ul>
<li><strong>Remote machine:</strong> wg0: 10.20.40.1 (behind public IP 163.172.161.0)</li>
<li><strong>Local machine:</strong> wg0: 10.20.40.2 (with eth0 on 192.168.88.207)</li>
<li><strong>Machines on remote LAN:</strong> 10.20.0.0/16</li>
<li><strong>Remote LAN Watchguard range:</strong> 10.20.40.0/16 -- note this is within the remote 10.20.0.0/16 range</li>
</ul>
<p>From my local machine, with minimal interaction, I want to be able to ping something like 10.20.<strong>10.30</strong>, and get a response.</p>
<p>Happily, now that the two endpoints are talking with each other, there's really not much that has to happen to get things working the way I want.</p>
<h2>Remote Config</h2>
<ul>
<li>
<p>Many Linux distros disable IPv4 packet forwarding by default. But in this case, we very much want this enabled. Edit your <code>/etc/sysctl.conf</code> file, and look for the line: <code>net.ipv4.ip_forward</code>, and set the value to 1. You may need to add this line manually, or uncomment it.</p>
</li>
<li>
<p>You'll also need to enable ProxyARP. This is another kernel setting that's usually disabled, so edit <code>/etc/sysctl.conf</code>, and add the following line: <code>net.ipv4.conf.all.proxy_arp = 1</code>.</p>
</li>
<li>
<p>Reload your kernel settings. A reboot will do the trick, or you could just run <code>sudo sysctl -p /etc/sysctl.conf</code>.</p>
</li>
</ul>
<h2>Starting WireGuard on Boot</h2>
<p>There are a variety options to do this, and if you're a seasoned sysadmin you probably already have a favourite way.</p>
<p>One option is to add <code>post-up wg-quick up wg0</code> to the tail of your eth0 block (or appropriate interface) in /etc/network/interfaces.</p>
<p>A second option (for systemd users) is to simply run <code>systemctl enable wg-quick@wg0</code>. This will tell systemd to bring the wg0 interface up once a network connection is established.</p>
<p>I only do this on the remote machine, because I don't want my local machine to be forever spinning up it's WireGuard connection; however I always want the remote machine listening for my packets. That said, there's probably no reason to avoid this; I just haven't done it yet.</p>
<h2>Local Config</h2>
<p>Here's the really cool bit. Since your remote machine is now set up to perform IPv4 forwaring and ProxyARP, the only thing you need to change on the local side is a single number. Or rather, a couple numbers.</p>
<ul>
<li>
<p>In your <code>/etc/WireGuard/wg0.conf</code> file, just expand the network range of your interface to include the entire remote LAN:</p>
<div class="highlight"><pre><span></span><code><span class="k">[Interface]</span>
<span class="na">...</span>
<span class="na">Address</span> <span class="o">=</span> <span class="s">10.20.40.2/16</span>
<span class="k">[Peer]</span>
<span class="na">...</span>
<span class="na">AllowedIPs</span> <span class="o">=</span> <span class="s">10.20.0.0/16</span>
</code></pre></div>
</li>
<li>
<p>Now reload your WireGuard config, either by rebooting, or running <code>sudo wg-quick down wg0 && sudo wg-quick up wg0</code>.</p>
</li>
</ul>
<p>That's all! When you make the above changes, wg-quick will modify your routing table so that <strong>any IP within 10.20.x.y</strong> will be sent over the wg0 interface. The remote host will dutifully forward the packet out into the rest of the network, and ProxyARP will take care of the rest:</p>
<div class="highlight"><pre><span></span><code>$ ping -c1 <span class="m">10</span>.20.10.31
PING <span class="m">10</span>.20.10.31 <span class="o">(</span><span class="m">10</span>.20.10.31<span class="o">)</span> <span class="m">56</span><span class="o">(</span><span class="m">84</span><span class="o">)</span> bytes of data.
<span class="m">64</span> bytes from <span class="m">10</span>.20.10.31: <span class="nv">icmp_seq</span><span class="o">=</span><span class="m">1</span> <span class="nv">ttl</span><span class="o">=</span><span class="m">63</span> <span class="nv">time</span><span class="o">=</span><span class="m">91</span>.8 ms
</code></pre></div>
<h2>Troubleshooting</h2>
<p>Okay so by now there's a really good chance that you've bumped into trouble. I've started on a basic <a href="https://www.ericlight.com/wireguard-part-three-troubleshooting.html">WireGuard troubleshooting guide</a>, but it only covers the issues that I bumped into. If you're still stuck after reading through that, ask a question on the WireGuard Mailing List, or reach out via IRC (#WireGuard on Freenode) - this is all on <a href="https://www.wireguard.com/#contact-the-team">the WireGuard website</a>.</p>
<h2>Wrap-up</h2>
<p>That should be all! When you reboot the remote server (I specify reboot, because you want to test that your solution can survive an outage at the remote site), you should be able to ping other things in the remote LAN without any additional interaction. I still manually run <code>wg-quick up wg0</code> on my local laptop, because I don't want to be connected remotely <em>all</em> the time.</p>
<h2>Thanks</h2>
<p>Huge gratitude to <a href="https://www.zx2c4.com/">Jason Donenfeld</a> (aka zx2c4) for spending his time not only reading this post, but also for sending me some fantastic feedback! I'd made some bungles in my original post on this topic, and he vastly helped my understanding.</p>
<p>If you do end up using WireGuard, <em>go forth and <a href="https://www.wireguard.com/#donations">donate</a></em>! Seriously, <strong>at very least</strong>, send Jason the cost of a local cup of coffee or a beer for his efforts.</p>
<p>Also, huge gratitude to another Jason (<a href="https://keybase.io/rendition">@rendition</a>) who has helped me develop from a junior network admin into a ... 'moderate' network admin. I've learned more in the last year than I ever thought possible. He's taught me nearly everything I know about managed networking, reviewed this post for me, and is actually the guy who introduced me to WireGuard originally!</p>WireGuard - Part One (Installation)2017-06-03T00:00:00+12:002017-06-11T00:00:00+12:00Eric Lighttag:www.ericlight.com,2017-06-03:/wireguard-part-one-installation.html<p><a href="https://wireguard.com/">WireGuard</a> is the most excellent VPN stack around. It's <em>really</em> fast, the concept of Cryptokey Routing is awesome, and I love the speed and simplicity benefits that come from opionionated cryptography. The protocol is so simple - expressed in a mere 4k lines of code - that it's auditable by anyone.</p>
<p><strong>But.</strong></p>
<p>With my initial naive approach, I found myself using HTTPS, over ports forwarded over SSH tunnels, connected over WireGuard. Although it was straightforward to get WireGuard working between two endpoints, I ended up in nested-crypto hell.</p>
<p>So, this brief series …</p><p><a href="https://wireguard.com/">WireGuard</a> is the most excellent VPN stack around. It's <em>really</em> fast, the concept of Cryptokey Routing is awesome, and I love the speed and simplicity benefits that come from opionionated cryptography. The protocol is so simple - expressed in a mere 4k lines of code - that it's auditable by anyone.</p>
<p><strong>But.</strong></p>
<p>With my initial naive approach, I found myself using HTTPS, over ports forwarded over SSH tunnels, connected over WireGuard. Although it was straightforward to get WireGuard working between two endpoints, I ended up in nested-crypto hell.</p>
<p>So, this brief series is about making WireGuard work as a VPN onto a different site. We'll start by making it work between two endpoints, and <a href="https://www.ericlight.com/wireguard-part-two-vpn-routing.html">we'll go forward from there</a>. My end goal is to have access to all the resources on a remote site, just by running <code>wg-quick up wg0</code>. </p>
<p>The endpoints I'm going to set up are at:</p>
<ul>
<li><strong>Remote machine:</strong> wg0: 10.20.40.1 (behind public IP 163.172.161.0)</li>
<li><strong>Local machine:</strong> wg0: 10.20.40.2</li>
</ul>
<h2>NAT Setup</h2>
<p>Chances are, your remote endpoint is behind a firewall of some sort. Pick a high port, and configure your firewall to forward UDP packets on that port through to your remote WireGuard endpoint. You don't need to do this on your local side, because reply traffic from the remote side will generally be handled by the stateful session part of your firewall.</p>
<p>Many routers and firewalls offer port address translation (also known as PAT) as part of port forwarding or NAT. This is when a packet hits the firewall on (say) port 57432, and the firewall puts it on the LAN to port 22, for example. You don't want this. I think it's possible with WireGuard, but it adds complexity without benefit.</p>
<h2>Config - Remote Site</h2>
<ul>
<li><a href="https://www.wireguard.com/install/">Install WireGuard</a></li>
<li>
<p>Generate your keys. The following will create a public key and a stub config in /etc/WireGuard/:</p>
<div class="highlight"><pre><span></span><code><span class="n">cd</span><span class="w"> </span><span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">WireGuard</span><span class="w"></span>
<span class="n">umask</span><span class="w"> </span><span class="mi">077</span><span class="w"></span>
<span class="n">printf</span><span class="w"> </span><span class="ss">"[Interface]\nPrivateKey = "</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="n">wg0</span><span class="p">.</span><span class="n">conf</span><span class="w"></span>
<span class="n">wg</span><span class="w"> </span><span class="n">genkey</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">tee</span><span class="w"> </span><span class="o">-</span><span class="n">a</span><span class="w"> </span><span class="n">wg0</span><span class="p">.</span><span class="n">conf</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">wg</span><span class="w"> </span><span class="n">pubkey</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="n">publickey</span><span class="w"></span>
</code></pre></div>
</li>
<li>
<p>Edit your config to match:</p>
<div class="highlight"><pre><span></span><code><span class="k">[Interface]</span>
<span class="na">PrivateKey</span> <span class="o">=</span> <span class="s">WhAt3v3R= (this is the private key generated on this machine)</span>
<span class="na">ListenPort</span> <span class="o">=</span> <span class="s">12345 (this is the UDP port you've forwarded from your firewall)</span>
<span class="na">Address</span> <span class="o">=</span> <span class="s">10.20.40.1/24 (this will be the IP given to the wg0 interface)</span>
<span class="k">[Peer]</span>
<span class="na">PublicKey</span> <span class="o">=</span> <span class="s">(leave this blank for now; you'll paste in your local public key here soon)</span>
<span class="na">AllowedIPs</span> <span class="o">=</span> <span class="s">10.20.40.0/24 (this is the range of WireGuard IP addresses that this Peer's key can be used from)</span>
</code></pre></div>
</li>
<li>
<p>That should be all you need to configure on the remote side for now. Save your wg0.conf file, and bring the interface up:</p>
<div class="highlight"><pre><span></span><code><span class="err">wg-quick up wg0</span>
<span class="err">ping -c1 10.20.40.1</span>
</code></pre></div>
</li>
<li>
<p>You should see a bunch of actions performed by wg-quick, and a reply packet from your ping. Now onto the local side.</p>
</li>
</ul>
<h2>Config - Local Machine</h2>
<ul>
<li>Install WireGuard and generate your keys, as per the first two steps above.</li>
<li>
<p>Edit your configuration again:</p>
<div class="highlight"><pre><span></span><code><span class="k">[Interface]</span>
<span class="na">PrivateKey</span> <span class="o">=</span> <span class="s">WhAt3v3R+PaRt-tw0= (this is the private key generated on this machine)</span>
<span class="na">ListenPort</span> <span class="o">=</span> <span class="s">12345 (this is the UDP port again; I don't think they have to be the same)</span>
<span class="na">Address</span> <span class="o">=</span> <span class="s">10.20.40.2/24 (note - different IP address, but in the same range)</span>
<span class="k">[Peer]</span>
<span class="na">PublicKey</span> <span class="o">=</span> <span class="s">?????????? (copy the public key from the REMOTE server here)</span>
<span class="na">Endpoint</span> <span class="o">=</span> <span class="s">163.172.161.0:12345 (enter the PUBLIC IP address of the remote site, plus the forwarded port)</span>
<span class="na">AllowedIPs</span> <span class="o">=</span> <span class="s">10.20.40.0/24 (specifying that packets using this key must come from within 10.20.40.x)</span>
</code></pre></div>
</li>
<li>
<p>Now that you've got a local public key, take a second to paste it into the Peer public key section on the remote server.</p>
</li>
<li>
<p>Once you're finished you should be able to bring the interface up and ping it:</p>
<div class="highlight"><pre><span></span><code><span class="err">wg-quick up wg0</span>
<span class="err">ping -c1 10.20.40.2</span>
</code></pre></div>
</li>
<li>
<p>... and you should even be able to ping the remote server as well:</p>
<div class="highlight"><pre><span></span><code><span class="err">ping -c1 10.20.40.1</span>
</code></pre></div>
</li>
</ul>
<h2>Gotten Stuck?</h2>
<p>At this stage, there are actually a few ways that this can go wrong, even though we haven't done much. Here's a quick summary of everything we've done:</p>
<ul>
<li>Installed WireGuard at both ends</li>
<li>Set up your NAT rule on the remote side </li>
<li>Created a private and public key on each side</li>
<li>Put each public key in the opposite side's [Peer] config</li>
<li>Put a suitable IP address on each side</li>
</ul>
<p>If you've nailed each of those and you're still having trouble, you can have a quick look at the brief Troubleshooting guide I've put together as <a href="https://www.ericlight.com/wireguard-part-three-troubleshooting.html">Part Three</a>.</p>
<h2>Onto Part Two</h2>
<p>That should be all you need to get WireGuard working between two machines on two different sites. So far we haven't done anything either interesting or uncommon - this is all the basic stuff you'll find on the <a href="https://www.wireguard.com/quickstart/">WireGuard Quick Start</a> page, although expressed slightly differently. <a href="https://www.ericlight.com/wireguard-part-two-vpn-routing.html">The next article</a> will be a bit more about intra-site routing.</p>
<h2>Thanks</h2>
<p>Huge gratitude to <a href="https://www.zx2c4.com/">Jason Donenfeld</a> (aka zx2c4) for spending his time not only reading this post, but also for sending me some fantastic feedback! I'd made some bungles in my original post on this topic, and he vastly helped my understanding.</p>
<p>If you do end up using WireGuard, <em>go forth and <a href="https://www.wireguard.com/#donations">donate</a></em>! Seriously, <strong>at very least</strong>, send Jason the cost of a local cup of coffee or a beer for his efforts.</p>
<p>Also, huge gratitude to another Jason (<a href="https://keybase.io/rendition">@rendition</a>) who has helped me develop from a junior network admin into a ... 'moderate' network admin. I've learned more in the last year than I ever thought possible. He's taught me nearly everything I know about managed networking, reviewed this post for me, and is actually the guy who introduced me to WireGuard originally!</p>Pan-fried Spicy Miso Chicken2017-05-29T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2017-05-29:/pan-fried-spicy-miso-chicken.html<p>Jeez I just discovered I've only posted a single recipe on this. Time to change that.</p>
<p>Chicken for dinner tonight. I was feeling a little adventurous, and definitely wanted some miso involved, but also felt like cayenne pepper and shallow-fried chicken strips. Here's the result! This went really well on a base of bulgur wheat, and with a side of stir fried veggies.</p>
<h2>Ingredients</h2>
<ul>
<li>Two chicken breasts, skinless</li>
<li>2 tsp miso paste</li>
<li>2/3 cup plain flour</li>
<li>2 tsp celery salt</li>
<li>1 1/2 tsp onion powder</li>
<li>2 tsp smoked …</li></ul><p>Jeez I just discovered I've only posted a single recipe on this. Time to change that.</p>
<p>Chicken for dinner tonight. I was feeling a little adventurous, and definitely wanted some miso involved, but also felt like cayenne pepper and shallow-fried chicken strips. Here's the result! This went really well on a base of bulgur wheat, and with a side of stir fried veggies.</p>
<h2>Ingredients</h2>
<ul>
<li>Two chicken breasts, skinless</li>
<li>2 tsp miso paste</li>
<li>2/3 cup plain flour</li>
<li>2 tsp celery salt</li>
<li>1 1/2 tsp onion powder</li>
<li>2 tsp smoked paprika</li>
<li>1 tsp chicken stock powder</li>
<li>1/8 tsp cayenne pepper</li>
<li>1/2 tsp black pepper</li>
</ul>
<h2>Method</h2>
<ul>
<li>Cut the chicken into strips, sized similarly to your two thumbs together.</li>
<li>Sift all the dry ingredients into a bowl, and stir or shake until mixed.</li>
<li><strong>Taste your flour coating!!</strong> Make sure it's delicious, and make sure it's spicy enough.</li>
<li>Mix your miso paste with a little hot water until smooth. <strong>It should be quite thick</strong>, you don't want it dripping off.</li>
<li>Coat all the chicken in the miso paste.</li>
<li>Roll the chicken strips in the flour until thoroughly coated.</li>
<li>Pan-fry in a very hot pan, for about 2 minutes per side.</li>
</ul>
<p>Enjoy!</p>RingZer0team CTF - Linux Sysadmin challenges2017-05-28T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2017-05-28:/ringzer0team-ctf-linux-sysadmin-challenges.html<p>There are a bunch of fantastic Capture The Flag security challenges on <a href="https://www.ringzer0team.com">RingZer0Team.com</a>. I've been working through some of these for a wee while now, and with the <a href="https://www.cybersecuritychallenge.org.nz/">New Zealand Cyber Security Challenge</a> coming up again soon, I thought I'd get back into some of them.</p>
<p>The Sysadmin Linux series of challenges is where you're trying to breach the security of a Linux system. I actually finished most of these last year, but I wanted to finish my last two. Of course, to get to the last two stages …</p><p>There are a bunch of fantastic Capture The Flag security challenges on <a href="https://www.ringzer0team.com">RingZer0Team.com</a>. I've been working through some of these for a wee while now, and with the <a href="https://www.cybersecuritychallenge.org.nz/">New Zealand Cyber Security Challenge</a> coming up again soon, I thought I'd get back into some of them.</p>
<p>The Sysadmin Linux series of challenges is where you're trying to breach the security of a Linux system. I actually finished most of these last year, but I wanted to finish my last two. Of course, to get to the last two stages, you need to use the flags from the <em>previous</em> stages. So I'm revisiting them.</p>
<h2>Level 1 - Morpheus -> Trinity</h2>
<p>We start by SSH'ing into a particular user account on the ringzer0team server:</p>
<div class="highlight"><pre><span></span><code><span class="err">You have mail.</span>
<span class="err">Last login: Thu Apr 27 02:52:40 2017 from <somewhere></span>
<span class="err">morpheus@forensics:~$</span>
</code></pre></div>
<p>There's only one file in the home folder, and I can't read it. There's a /home/trinity folder with full read access, but also nothing legible.</p>
<p>The flag for level 1 is found by running ps aux, which reveals what appears to be Trinity's password:</p>
<div class="highlight"><pre><span></span><code><span class="err">root 3241 0.0 0.0 4188 572 ? S Jan14 1:44 /bin/sh /root/backup.sh -u trinity -p Flag-<redacted></span>
</code></pre></div>
<h2>Level 2 - Morpheus -> Architect</h2>
<p>Aha, and the flag for level two is in /etc/fstab, which contains what appears to be The Architect's password, in base64:</p>
<div class="highlight"><pre><span></span><code><span class="err">/dev/sr0 /media/cdrom0 udf,iso9660 user,noauto 0 0</span>
<span class="err">/dev/fd0 /media/floppy0 auto rw,user,noauto 0 0</span>
<span class="err">#//TheMAtrix/phone /media/Matrix cifs username=architect,password=$(base64 -d "<redacted>"),iocharset=utf8,sec=ntlm 0 0</span>
</code></pre></div>
<h2>Level 3 - The Architect</h2>
<p>Level 3 requires you to log on as architect, using the password we discovered earlier. The only clue is "dig for password".</p>
<p>This bit got a bit harder. There are a couple possible hints in architect's mail file, including a bunch of attempts to mount a cifs volume, and reference to a file in /backup/.</p>
<p>Digging through the files in /backup left me at a loss. There are references to /tmp/Gathering.py, but that's a challenge for later (cypher's challenge). After some digging I located /var/tmp/.swl, which contained some MySQL credentials!</p>
<div class="highlight"><pre><span></span><code><span class="n">mysql</span><span class="o">></span> <span class="k">show</span> <span class="n">tables</span><span class="p">;</span>
<span class="o">+</span><span class="c1">----------------+</span>
<span class="o">|</span> <span class="n">Tables_in_arch</span> <span class="o">|</span>
<span class="o">+</span><span class="c1">----------------+</span>
<span class="o">|</span> <span class="n">arch</span> <span class="o">|</span>
<span class="o">|</span> <span class="n">flag</span> <span class="o">|</span>
<span class="o">+</span><span class="c1">----------------+</span>
<span class="mi">2</span> <span class="k">rows</span> <span class="k">in</span> <span class="k">set</span> <span class="p">(</span><span class="mi">0</span><span class="p">.</span><span class="mi">00</span> <span class="n">sec</span><span class="p">)</span>
<span class="n">mysql</span><span class="o">></span> <span class="k">select</span> <span class="o">*</span> <span class="k">from</span> <span class="n">arch</span><span class="p">;</span>
<span class="o">+</span><span class="c1">------+-----------------------+</span>
<span class="o">|</span> <span class="n">id</span> <span class="o">|</span> <span class="n">arch</span> <span class="o">|</span>
<span class="o">+</span><span class="c1">------+-----------------------+</span>
<span class="o">|</span> <span class="mi">1</span> <span class="o">|</span> <span class="n">The</span> <span class="n">one</span> <span class="o">|</span>
<span class="o">|</span> <span class="mi">1</span> <span class="o">|</span> <span class="n">The</span> <span class="k">null</span> <span class="n">one</span> <span class="o">|</span>
<span class="o">|</span> <span class="mi">1</span> <span class="o">|</span> <span class="n">The</span> <span class="n">mother</span> <span class="k">of</span> <span class="n">the</span> <span class="n">one</span> <span class="o">|</span>
<span class="o">|</span> <span class="mi">1</span> <span class="o">|</span> <span class="n">The</span> <span class="n">father</span> <span class="k">of</span> <span class="n">the</span> <span class="n">one</span> <span class="o">|</span>
<span class="o">|</span> <span class="mi">1</span> <span class="o">|</span> <span class="n">The</span> <span class="n">flag</span> <span class="k">of</span> <span class="n">the</span> <span class="n">one</span> <span class="o">|</span>
<span class="o">|</span> <span class="mi">1</span> <span class="o">|</span> <span class="n">The</span> <span class="k">null</span> <span class="n">one</span> <span class="o">|</span>
<span class="o">+</span><span class="c1">------+-----------------------+</span>
<span class="mi">6</span> <span class="k">rows</span> <span class="k">in</span> <span class="k">set</span> <span class="p">(</span><span class="mi">0</span><span class="p">.</span><span class="mi">00</span> <span class="n">sec</span><span class="p">)</span>
<span class="n">mysql</span><span class="o">></span> <span class="k">select</span> <span class="o">*</span> <span class="k">from</span> <span class="n">flag</span><span class="p">;</span>
<span class="o">+</span><span class="c1">---------------------------------+</span>
<span class="o">|</span> <span class="n">flag</span> <span class="o">|</span>
<span class="o">+</span><span class="c1">---------------------------------+</span>
<span class="o">|</span> <span class="n">FLAG</span><span class="o">-<</span><span class="n">redacted</span><span class="o">></span> <span class="o">|</span>
<span class="o">+</span><span class="c1">---------------------------------+</span>
<span class="mi">1</span> <span class="k">row</span> <span class="k">in</span> <span class="k">set</span> <span class="p">(</span><span class="mi">0</span><span class="p">.</span><span class="mi">00</span> <span class="n">sec</span><span class="p">)</span>
</code></pre></div>
<p>Yasss after a solid hour of digging, I've found the flag for the third level!</p>
<h2>Level Four - Morpheus -> Oracle</h2>
<p>Again we're logging on as morpheus, but this time the goal is to access the oracle account.</p>
<p>Lots of tasty stuff under /var/tmp/.viminfo, now that I've found it. References to files in /backup/, to /tmp/Gathering.py, /tmp/mail_cypher</p>
<p>Don't make the mistake of trying to cat .swo; it'll eat your console session.</p>
<p>Found this interesting thing in mail, but it's not helpful: <code>forensics.localdomain : Apr 14 21:14:33 : morpheus : user NOT in sudoers ; TTY=pts/4 ; PWD=/home/trinity ; USER=root ; COMMAND=/usr/sbin/usermod -aG neo morpheus</code></p>
<p>In one of the /backup files, I found the remains of an SSH key, and it worked! Access to the oracle account achieved. In the home folder, we've got a handy-dandy Base64-encoded flag in flag.txt.</p>
<h2>Level Five - Oracle Encrypted File</h2>
<p>There's a file in the oracle home folder named encflag.txt.enc:</p>
<div class="highlight"><pre><span></span><code><span class="err">U2FsdGVkX1+dCl4WEHNJKBqA8a4fQeheOgA7oiNmjwlJQvGaQAgqcIsGRIcbdHKF</span>
<span class="err">heSs51JRSEmOLqVyGvoxDA--</span>
</code></pre></div>
<p>Decoding the base64 returns a binary blob, prefixed with the string "Salted". This is one of the levels that I never completed originally, so maybe it's time to give it another crack.</p>
<p>A quick google of "salted base64" reveals an <a href="https://security.stackexchange.com/a/124333">interesting comment on StackExchange</a>. Apparently I'm looking at a file encrypted with the OpenSSL 'enc' command, so I first copy the file to my own computer to work.</p>
<p>I discover that the command <code>openssl enc -in testfile -d -a</code> will un-base64 it, then load the file in. I need to pass it a password to decrypt with though, so now I need to find that.</p>
<p>Oh my god I just did <code>cat .*</code> in the oracle home folder and literally found an alias that reads and decrypts the file. I can't believe that took me almost an hour.</p>
<p>There are no words.</p>
<h2>Level Six - Trinity -> Neo</h2>
<p>Okay getting serious now. Using Trinity's account, I need to find the password for the neo account.</p>
<p>It's a bit noisy on login:</p>
<div class="highlight"><pre><span></span><code><span class="err">You have mail.</span>
<span class="err">Last login: Tue Apr 25 16:29:29 2017 from <le blah></span>
<span class="c">-bash: hello: command not found</span>
<span class="err">Sup Neo!</span>
<span class="c">ls: cannot open directory /home/neo: Permission denied</span>
<span class="c">cat: phonebook: Permission denied</span>
</code></pre></div>
<p>A vague tickle in my memory prompted me to run sudo -l right off the bat. Rewarded with:</p>
<div class="highlight"><pre><span></span><code><span class="err">User trinity may run the following commands on this host:</span>
<span class="err"> (neo) /bin/cat /home/trinity/*</span>
</code></pre></div>
<p>So of course I immediately run <code>sudo -u neo /bin/cat /home/trinity/*</code></p>
<p>This gives us a 'phone book' containing:</p>
<div class="highlight"><pre><span></span><code><span class="n">The</span> <span class="n">Oracle</span> <span class="mi">1800</span><span class="o">-</span><span class="mi">133</span><span class="o">-</span><span class="mi">7133</span>
<span class="n">Persephone</span> <span class="mi">345</span><span class="o">-</span><span class="mi">555</span><span class="o">-</span><span class="mi">1244</span>
<span class="k">copy</span> <span class="n">made</span> <span class="k">by</span> <span class="n">Cypher</span> <span class="k">copy</span> <span class="n">utility</span> <span class="k">on</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">neo</span><span class="o">/</span><span class="n">phonebook</span>
</code></pre></div>
<p>Trinity's .bashrc contains a bit of kruft:</p>
<div class="highlight"><pre><span></span><code><span class="err">hello neo</span>
<span class="err">echo "Sup Neo!"</span>
<span class="err">$(ls -lart /home/neo)</span>
<span class="err">cat phonebook</span>
</code></pre></div>
<p>Really not useful. I remember finding Trinity's password with <code>ps aux</code>:</p>
<div class="highlight"><pre><span></span><code><span class="err">root 3241 0.0 0.0 4188 572 ? S Jan14 1:47 /bin/sh /root/backup.sh -u trinity -p Flag-08grILsn3ekqhDK7cKBV6ka8B</span>
</code></pre></div>
<p>It looks a little bit like a MySQL connection string, so I try that but no dice. Nothing under /var/tmp this time, and grep doesn't find anything useful under the /backup goldmine.</p>
<p>There's some weirdness under /etc/passwd. I don't know what this means, but saving it for later:</p>
<div class="highlight"><pre><span></span><code><span class="n">trinity</span><span class="o">:</span><span class="n">x</span><span class="o">:</span><span class="mi">1002</span><span class="o">:</span><span class="mi">1002</span><span class="o">:</span><span class="n">trinity</span><span class="o">,%,</span><span class="n">lsdf</span><span class="o">(</span><span class="mi">940998</span><span class="o">+(</span><span class="n">n</span><span class="o">.~,</span><span class="mi">3</span><span class="o">):/</span><span class="n">home</span><span class="sr">/trinity:/bin/</span><span class="n">bash</span>
</code></pre></div>
<p>I looked through the mail file, but nothing jumped out at me there. Also trawled again through /backup, as well as /var/backups. Then /etc and /var. Argh.</p>
<p>Finally I start looking for Persephone. Nothing helpful, but it reminds me of the last line in the phonebook.</p>
<p>copy made by Cypher copy utility on /home/neo/phonebook</p>
<p>And then I remember that the sudo command allows a * at the end of the cat command, which might allow me to do path traversal...</p>
<div class="highlight"><pre><span></span><code><span class="err">sudo -u neo /bin/cat /home/trinity/../neo/phonebook</span>
</code></pre></div>
<p>Finally, after a whole hour of digging, I'm awarded Neo's password!</p>
<h2>Level 7 - Neo is Not Alone</h2>
<p>I don't know what this clue means, but I bet it has something to do with Persephone. Persephone comes from Greek mythology as one of Zeus' daughters, and the goddess of the underworld. Does that help me here? I don't know, it's getting late...</p>
<p>I run <code>cat .*</code> in Neo's home directory to see if there's anything hiding there, but no luck this time. Also nothing for <code>sudo -l</code>.</p>
<p>There's an unreadable file (owned by root) called 'result.stat', that's probably related to something. I browse the mail history and see:</p>
<div class="highlight"><pre><span></span><code><span class="err">forensics.localdomain : Dec 7 14:08:08 : neo : user NOT in sudoers ; TTY=pts/2 ; PWD=/home/neo ; USER=morpheus ; COMMAND=/home/morpheus/egrep /home/morpheus/../neo/result.stat</span>
</code></pre></div>
<p>That could be handy. I do remember an egrep in /home/neo, will have a look. Lots of reference to /bin/monitor, too. </p>
<p>I'm only in the neo group, so nothing to see there.</p>
<p>Running <code>ps aux | grep neo</code> shows a heap of /bin/monitor processes started by root, but running under neo. There's also a "SCREEN" instance there, but running <code>screen -D -RR</code> doesn't reclaim it, so something's up there. I'm pretty sure there's something there in /bin/monitor.</p>
<p>In all honesty this one had me beat. It was half-past midnight and I was exhausted. I knew that there was something special about /bin/monitor, and I knew there was something special about the fact that it was running as neo. But I took the expedient route and had a quick google. I found the answer at <a href="http://blog.dornea.nu/2016/10/30/ringzer0-ctf-sysadmin-linux/">http://blog.dornea.nu/2016/10/30/ringzer0-ctf-sysadmin-linux/</a> - without this I could have been looking for years. However, as is so often the case, this tutorial was the basis of some great learning for me.</p>
<p>Because the process is owned by neo, and because /bin/monitor could be <em>read</em> by neo, it meant I could run a stack trace. <em>I have never done this before</em> - no false impressions here, I totally relied on that dornea.ru page to tip me off to the usage of strace. But once I knew that, I had the flag.</p>
<p>I was very well misled by this one, actually. The Persephone comment in the phonebook totally led me down the wrong path, and I spent quite a long time searching for her details on the system. It was the reddest herring possible.</p>
<h2>Level 8 - Morpheus -> Cypher</h2>
<p>Okay it's late now so I'm going to try to thrash this one quick. Nothing in <code>ps aux</code> for cypher. Grepping /backup found a python file and a dump showing a cron job runs this file every minute. The contents of the python file are:</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">os</span>
<span class="n">os</span><span class="o">.</span><span class="n">system</span><span class="p">(</span><span class="s1">'ps aux > /tmp/28JNvE05KBltE8S7o2xu'</span><span class="p">)</span>
</code></pre></div>
<p>I can't read the output file, but I can edit the python script! This is gonna be easy.</p>
<p>After a little bit of trial and error, I edited the python script to first list the contents of the /home/cypher folder, and after that, to output the contents of /home/cypher/flag.txt</p>
<p>It's important to note that the python file is recreated every three minutes when it's run, so you need to redo your changes for every iteration.</p>
<h1>Fin</h1>
<p>That's the end! I'm quite pleased I've managed to finish all of the Sysadmin Linux section. Of course that's also scary, because it means I need to break into the other sections. That's OK though... it's a good time to do it!</p>RingZer0team CTF - Challenge 1482017-05-27T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2017-05-27:/ringzer0team-ctf-challenge-148.html<p>There are a bunch of fantastic Capture The Flag security challenges on <a href="https://www.ringzer0team.com">RingZer0Team.com</a>. I've been working through some of these for a wee while now, and with the <a href="https://www.cybersecuritychallenge.org.nz/">New Zealand Cyber Security Challenge</a> coming up again soon, I thought I'd get back into some of them.</p>
<p>Challenge 148 ("Sysadmin Linux Level 2") is one of a series of challenges where you're trying to breach the security of a Linux system. I actually finished most of these last year, but I wanted to finish my last two. Of course, to …</p><p>There are a bunch of fantastic Capture The Flag security challenges on <a href="https://www.ringzer0team.com">RingZer0Team.com</a>. I've been working through some of these for a wee while now, and with the <a href="https://www.cybersecuritychallenge.org.nz/">New Zealand Cyber Security Challenge</a> coming up again soon, I thought I'd get back into some of them.</p>
<p>Challenge 148 ("Sysadmin Linux Level 2") is one of a series of challenges where you're trying to breach the security of a Linux system. I actually finished most of these last year, but I wanted to finish my last two. Of course, to get to the last two stages, you need to use the flags from the <em>previous</em> stages. So I'm revisiting them.</p>
<p>We start by SSH'ing into a particular user account on the ringzer0team server:</p>
<p>You have mail.
Last login: Thu Apr 27 02:52:40 2017 from <somewhere>
morpheus@forensics:~$ </p>
<p>There's only one file in the home folder, and I can't read it. There's a /home/trinity folder with full read access, but also nothing legible.</p>
<p>Running ps aux reveals what appears to be Trinity's password:</p>
<p>root 3241 0.0 0.0 4188 572 ? S Jan14 1:44 /bin/sh /root/backup.sh -u trinity -p Flag-<redacted></p>
<p>Aha, and /etc/fstab contains what appears to be The Architect's password, in base64:</p>
<p>/dev/sr0 /media/cdrom0 udf,iso9660 user,noauto 0 0
/dev/fd0 /media/floppy0 auto rw,user,noauto 0 0
#//TheMAtrix/phone /media/Matrix cifs username=architect,password=$(base64 -d "<redacted>"),iocharset=utf8,sec=ntlm 0 0</p>
<p>Great! Now I can carry on to my <em>actual</em> goal, which was to nail challenge 91 ("Sysadmin Linux Level 7")!</p>RingZer0team CTF - Challenge 572017-05-05T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2017-05-05:/ringzer0team-ctf-challenge-57.html<p>This is a continuation of my series on <a href="https://www.ringzer0team.com">RingZer0Team.com</a>. </p>
<p>Challenge 57 ("Hash Breaker Reloaded", under the Coding Challenges) is one of a series of challenges where you're simply presented with a hash - you need to return the plaintext value to the page within 3 seconds.</p>
<p>In contrast to <a href="https://www.ericlight.com/ringzer0team-ctf-challenge-56.html">Challenge 56</a>, <strong>this</strong> challenge also includes a salt:</p>
<div class="highlight"><pre><span></span><code><span class="n">You</span><span class="w"> </span><span class="n">have</span><span class="w"> </span><span class="mi">3</span><span class="w"> </span><span class="n">seconds</span><span class="w"> </span><span class="k">to</span><span class="w"> </span><span class="k">break</span><span class="w"> </span><span class="n">this</span><span class="w"> </span><span class="n">hash</span><span class="w"></span>
<span class="n">Send</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">answer</span><span class="w"> </span><span class="n">back</span><span class="w"> </span><span class="k">using</span><span class="w"> </span><span class="nl">https</span><span class="p">:</span><span class="o">//</span><span class="n">ringzer0team</span><span class="p">.</span><span class="n">com</span><span class="o">/</span><span class="n">challenges</span><span class="o">/</span><span class="mi">57</span><span class="o">/[</span><span class="n">clear_text</span><span class="o">]</span><span class="w"></span>
<span class="c1">----- BEGIN HASH -----</span>
<span class="n">ab9507edbb2501b3c02e47c51af0178d68655980</span><span class="w"></span>
<span class="c1">----- END HASH -----</span>
<span class="c1">----- BEGIN SALT -----</span>
<span class="n">c2ac9d8d004b4011d0864e76c7ebaaccfd18464bb8ff66bdbf19a703eb95a944</span><span class="w"></span>
<span class="c1">----- END SALT -----</span>
</code></pre></div>
<p>The hash looks like …</p><p>This is a continuation of my series on <a href="https://www.ringzer0team.com">RingZer0Team.com</a>. </p>
<p>Challenge 57 ("Hash Breaker Reloaded", under the Coding Challenges) is one of a series of challenges where you're simply presented with a hash - you need to return the plaintext value to the page within 3 seconds.</p>
<p>In contrast to <a href="https://www.ericlight.com/ringzer0team-ctf-challenge-56.html">Challenge 56</a>, <strong>this</strong> challenge also includes a salt:</p>
<div class="highlight"><pre><span></span><code><span class="n">You</span><span class="w"> </span><span class="n">have</span><span class="w"> </span><span class="mi">3</span><span class="w"> </span><span class="n">seconds</span><span class="w"> </span><span class="k">to</span><span class="w"> </span><span class="k">break</span><span class="w"> </span><span class="n">this</span><span class="w"> </span><span class="n">hash</span><span class="w"></span>
<span class="n">Send</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">answer</span><span class="w"> </span><span class="n">back</span><span class="w"> </span><span class="k">using</span><span class="w"> </span><span class="nl">https</span><span class="p">:</span><span class="o">//</span><span class="n">ringzer0team</span><span class="p">.</span><span class="n">com</span><span class="o">/</span><span class="n">challenges</span><span class="o">/</span><span class="mi">57</span><span class="o">/[</span><span class="n">clear_text</span><span class="o">]</span><span class="w"></span>
<span class="c1">----- BEGIN HASH -----</span>
<span class="n">ab9507edbb2501b3c02e47c51af0178d68655980</span><span class="w"></span>
<span class="c1">----- END HASH -----</span>
<span class="c1">----- BEGIN SALT -----</span>
<span class="n">c2ac9d8d004b4011d0864e76c7ebaaccfd18464bb8ff66bdbf19a703eb95a944</span><span class="w"></span>
<span class="c1">----- END SALT -----</span>
</code></pre></div>
<p>The hash looks like another SHA-1, but of course the online hash reversers don't have the <em>now-salted</em> hash in their rainbow tables. I figured that the challenge was a simple continuation of the previous challenge, so I crossed my fingers and guessed the hash was simply a number (from last time), concatenated with the plain-text salt.</p>
<p>... And I was lucky! The below code got me the flag: </p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21</pre></div></td><td class="code"><div class="highlight"><pre><span></span><code><span class="ch">#!/usr/bin/python3</span>
<span class="kn">from</span> <span class="nn">requests</span> <span class="kn">import</span> <span class="n">get</span>
<span class="kn">from</span> <span class="nn">hashlib</span> <span class="kn">import</span> <span class="n">sha1</span>
<span class="kn">from</span> <span class="nn">re</span> <span class="kn">import</span> <span class="n">search</span>
<span class="n">url</span><span class="o">=</span><span class="s1">'https://ringzer0team.com/challenges/57'</span>
<span class="n">session</span><span class="o">=</span><span class="nb">dict</span><span class="p">(</span><span class="n">PHPSESSID</span><span class="o">=</span><span class="s1">'<blahblah>'</span><span class="p">)</span>
<span class="n">resp</span><span class="o">=</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">,</span><span class="n">cookies</span><span class="o">=</span><span class="n">session</span><span class="p">)</span>
<span class="nb">hash</span><span class="o">=</span><span class="n">resp</span><span class="o">.</span><span class="n">text</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"-----"</span><span class="p">)[</span><span class="mi">2</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"</span><span class="se">\t</span><span class="s2">"</span><span class="p">)[</span><span class="mi">2</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"<"</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="n">salt</span><span class="o">=</span><span class="n">resp</span><span class="o">.</span><span class="n">text</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"-----"</span><span class="p">)[</span><span class="mi">6</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"</span><span class="se">\t</span><span class="s2">"</span><span class="p">)[</span><span class="mi">2</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"<"</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="n">newhash</span><span class="o">=</span><span class="s1">''</span>
<span class="n">salt</span><span class="o">=</span><span class="n">salt</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s1">'utf-8'</span><span class="p">)</span>
<span class="n">x</span><span class="o">=</span><span class="mi">0</span>
<span class="k">while</span> <span class="n">newhash</span> <span class="o">!=</span> <span class="nb">hash</span><span class="p">:</span>
<span class="n">newhash</span><span class="o">=</span><span class="n">sha1</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s1">'utf-8'</span><span class="p">)</span><span class="o">+</span><span class="n">salt</span><span class="p">)</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"</span><span class="si">%s</span><span class="s2"> = </span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">newhash</span><span class="p">,</span> <span class="n">x</span><span class="p">))</span>
<span class="n">x</span><span class="o">+=</span><span class="mi">1</span>
<span class="n">resp</span><span class="o">=</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="o">+</span><span class="s1">'/'</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">x</span><span class="o">-</span><span class="mi">1</span><span class="p">),</span><span class="n">cookies</span><span class="o">=</span><span class="n">session</span><span class="p">)</span>
<span class="n">flag</span><span class="o">=</span><span class="n">search</span><span class="p">(</span><span class="s2">"FLAG-.</span><span class="si">{24}</span><span class="s2">"</span><span class="p">,</span><span class="n">resp</span><span class="o">.</span><span class="n">text</span><span class="p">)</span><span class="o">.</span><span class="n">group</span><span class="p">()</span>
<span class="nb">print</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
</code></pre></div>
</td></tr></table>
<p>As last time, there's no error handling in that code, so if it runs for more than a few seconds it's probably toast.</p>RingZer0team CTF - Challenge 562017-05-02T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2017-05-02:/ringzer0team-ctf-challenge-56.html<p>There are a bunch of fantastic Capture The Flag security challenges on <a href="https://www.ringzer0team.com">RingZer0Team.com</a>. I've been working through some of these for a wee while now, and with the <a href="https://www.cybersecuritychallenge.org.nz/">New Zealand Cyber Security Challenge</a> coming up again soon, I thought I'd get back into some of them.</p>
<p>Challenge 56 ("Hash Breaker", under the Coding Challenges) is one of a series of challenges where you're simply presented with a hash - you need to return the plaintext value to the page within 3 seconds.</p>
<p>Of course, this is impossible to do manually …</p><p>There are a bunch of fantastic Capture The Flag security challenges on <a href="https://www.ringzer0team.com">RingZer0Team.com</a>. I've been working through some of these for a wee while now, and with the <a href="https://www.cybersecuritychallenge.org.nz/">New Zealand Cyber Security Challenge</a> coming up again soon, I thought I'd get back into some of them.</p>
<p>Challenge 56 ("Hash Breaker", under the Coding Challenges) is one of a series of challenges where you're simply presented with a hash - you need to return the plaintext value to the page within 3 seconds.</p>
<p>Of course, this is impossible to do manually, so it's a programming challenge.</p>
<p>The hash looks like a simple SHA-1, so I put it into an online hash reverser and discovered it's just a SHA1 hash of a random number. SHA1 is really fast, so this should be simple.</p>
<p>Here's how I tackled the problem:</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 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</pre></div></td><td class="code"><div class="highlight"><pre><span></span><code><span class="c1"># It's in Python3, because of reasons</span>
<span class="kn">from</span> <span class="nn">requests</span> <span class="kn">import</span> <span class="n">get</span>
<span class="kn">from</span> <span class="nn">hashlib</span> <span class="kn">import</span> <span class="n">sha1</span>
<span class="kn">from</span> <span class="nn">re</span> <span class="kn">import</span> <span class="n">search</span>
<span class="n">calculated_hash</span><span class="o">=</span><span class="s1">''</span>
<span class="n">x</span><span class="o">=</span><span class="mi">0</span>
<span class="c1"># Your session cookie needs to go here</span>
<span class="n">session</span><span class="o">=</span><span class="nb">dict</span><span class="p">(</span><span class="n">PHPSESSID</span><span class="o">=</span><span class="s1">'<cookie contents>'</span><span class="p">)</span>
<span class="c1"># Load the web page</span>
<span class="n">url</span><span class="o">=</span><span class="s1">'https://ringzer0team.com/challenges/56'</span>
<span class="n">resp</span><span class="o">=</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">,</span><span class="n">cookies</span><span class="o">=</span><span class="n">session</span><span class="p">)</span>
<span class="c1"># Extract the hash from the page contents</span>
<span class="n">target_hash</span><span class="o">=</span><span class="n">resp</span><span class="o">.</span><span class="n">text</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"-----"</span><span class="p">)[</span><span class="mi">2</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"</span><span class="se">\t</span><span class="s2">"</span><span class="p">)[</span><span class="mi">2</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"<"</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="c1"># Iterate hashes from zero until the calculated hash matches the target hash</span>
<span class="k">while</span> <span class="n">calculated_hash</span> <span class="o">!=</span> <span class="n">target_hash</span><span class="p">:</span>
<span class="n">calculated_hash</span><span class="o">=</span><span class="n">sha1</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s1">'utf-8'</span><span class="p">))</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"</span><span class="si">%s</span><span class="s2"> = </span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">calculated_hash</span><span class="p">,</span> <span class="n">x</span><span class="p">))</span>
<span class="n">x</span><span class="o">+=</span><span class="mi">1</span>
<span class="c1"># If we got here, yay! We found the key. Now submit it back to the site, and print our magic flag</span>
<span class="n">resp</span><span class="o">=</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="o">+</span><span class="s1">'/'</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">x</span><span class="o">-</span><span class="mi">1</span><span class="p">),</span><span class="n">cookies</span><span class="o">=</span><span class="n">session</span><span class="p">)</span>
<span class="n">flag</span><span class="o">=</span><span class="n">search</span><span class="p">(</span><span class="s2">"FLAG-.</span><span class="si">{24}</span><span class="s2">"</span><span class="p">,</span><span class="n">resp</span><span class="o">.</span><span class="n">text</span><span class="p">)</span><span class="o">.</span><span class="n">group</span><span class="p">()</span>
<span class="nb">print</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
</code></pre></div>
</td></tr></table>
<p>There's no error handling in that code, so if it runs for more than a few seconds it's probably toast.</p>HP Procurve's warn-and-disable2017-04-30T00:00:00+12:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2017-04-30:/hp-procurves-warn-and-disable.html<p>Since mid-2016, I've been working as a Network and Security Administrator. While I'd done a fair amount of networking previously, most of my experience had been with either unmanaged switches, or in a pre-built Cisco environment. Stepping into the world of managed networking was new for me, as was stepping into the world of HP Switches.</p>
<p>We were having recurring issues with a certain business unit looping ports on a switch. We had loop-protect running, but it was only set to disable the port after 5 seconds, and only for …</p><p>Since mid-2016, I've been working as a Network and Security Administrator. While I'd done a fair amount of networking previously, most of my experience had been with either unmanaged switches, or in a pre-built Cisco environment. Stepping into the world of managed networking was new for me, as was stepping into the world of HP Switches.</p>
<p>We were having recurring issues with a certain business unit looping ports on a switch. We had loop-protect running, but it was only set to disable the port after 5 seconds, and only for 300 seconds. This wasn't long enough (we've since set it to something more resilient).</p>
<p>During our attempts to minimise the impact of a network loop, we enabled this setting on our HP Procurve switches:</p>
<div class="highlight"><pre><span></span><code><span class="err">fault-finder broadcast-storm action warn-and-disable</span>
</code></pre></div>
<p>This seems simple enough. The fault-finder module will look for broadcast storms, and when found, will throw a syslog, an SNMP trap, and will disable the offending switch port.</p>
<p>Don't be fooled. <strong>This will absolutely wreck your breakfast.</strong></p>
<p>The fault-finder module is a <em>system-wide</em> setting, which means it applies to uplink ports as well. When a broadcast storm happens, all your distribution switches will see the broadcasts coming from... their uplink port. So of course, the switches disable their uplink to the rest of the network, neatly segregating themselves away from any services or central management.</p>
<p>Suffice to say, the next time we had a network loop there was a lot of walking and console cable madness, while we visited each of the distribution switches and manually re-enabled the disabled ports.</p>
<p>Lesson learned, loop-protect it is. (Until we get STP up campus-wide, of course)</p>Making Lektor work with grsecurity2016-10-29T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2016-10-29:/making-lektor-work-with-grsecurity.html<p>I started using <a href="https://grsecurity.net/">grsecurity</a> on my servers in 2015, and there's always a bit of <a href="https://wiki.archlinux.org/index.php/Grsecurity">tuning</a> <a href="http://hardenedlinux.org/system-security/2016/01/10/hardening-your-desktop-linux-mint-with-grsec.html">required</a>.</p>
<p>I was recently playing with <a href="https://www.getlektor.com">Lektor</a> (before I swapped to <a href="https://www.getpelican.com">Pelican</a>), and I had a bit of trouble with my grsec kernel. In particular, Lektor and Pelican are both run within a virtualenv Python environment, and grsec eats it like popcorn in two different ways:</p>
<p>1) TPE (Trusted Path Execution) throws a wobbly:</p>
<p><code>[253241.370019] grsec: From {ssh-origin-ip}: denied untrusted exec (due to file in world-writable directory) of /tmp/#50 by /usr/local …</code></p><p>I started using <a href="https://grsecurity.net/">grsecurity</a> on my servers in 2015, and there's always a bit of <a href="https://wiki.archlinux.org/index.php/Grsecurity">tuning</a> <a href="http://hardenedlinux.org/system-security/2016/01/10/hardening-your-desktop-linux-mint-with-grsec.html">required</a>.</p>
<p>I was recently playing with <a href="https://www.getlektor.com">Lektor</a> (before I swapped to <a href="https://www.getpelican.com">Pelican</a>), and I had a bit of trouble with my grsec kernel. In particular, Lektor and Pelican are both run within a virtualenv Python environment, and grsec eats it like popcorn in two different ways:</p>
<p>1) TPE (Trusted Path Execution) throws a wobbly:</p>
<p><code>[253241.370019] grsec: From {ssh-origin-ip}: denied untrusted exec (due to file in world-writable directory) of /tmp/#50 by /usr/local/lib/lektor/bin/lektor[lektor:60593] uid/euid:1000/1000 gid/egid:1000/1000, parent /bin/bash[bash:60581] uid/euid:1000/1000 gid/egid:1000/1000</code></p>
<p>This block occurs because the virtualenv violates grsecurity's Trusted Path Execution protection - the Python executable isn't under a trusted path, and the user isn't in the TPE-bypass group.</p>
<p>To resolve this one, add your user to the TPE group. This will allow the user to execute binaries which aren't in trusted locations:</p>
<p><strong><code>sudo usermod -aG grsec-tpe $USER</code></strong></p>
<p>2) RWX protection. This is a common problem with Python-based apps, even though Python has an exception (Edit 2020-04-12 - Issue 6 from <a href="https://github.com/thestinger/paxd/">https://github.com/thestinger/paxd/</a> has been deleted) by default.</p>
<p><code>[ 207.534876] grsec: From {ssh-source-ip}: denied RWX mmap of <anonymous mapping> by /usr/local/lib/lektor/bin/lektor[lektor:534] uid/euid:1000/1000 gid/egid:1000/1000, parent /bin/bash[bash:477] uid/euid:1000/1000 gid/egid:1000/1000</code></p>
<p>First, create your PaX ELF headers, and then disable grsec's MEMPROTECT extension on the included python2 binary, while you enable EMUTRAMP:</p>
<p><strong><code>sudo paxctl /usr/local/lib/lektor/bin/python2 -c</code><br>
<code>sudo paxctl /usr/local/lib/lektor/bin/python2 -Em</code></strong></p>
<p>Result!</p>Broken log times in APC's PCNS Appliance 4.12016-10-27T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2016-10-27:/broken-log-times-in-apcs-pcns-appliance-41.html<p>Schneider Electric's <a href="http://www.se.com/en/product-range/61933-powerchute-network-shutdown/">PowerChute Network Shutdown</a> is a piece of software which communicates with your local UPS, and initiates system shutdown if the UPS battery is unable to continue providing power. This helps to preserve file integrity in the event of a prolonged power failure.</p>
<p>Previously, you had to install the PCNS client separately on each virtual machine. Since then though, APC have released a <a href="https://solutionexchange.vmware.com/store/products/apc-powerchute-network-shutdown-v4-1-for-vmware">PCNS VMware Appliance</a> which is installed directly into vCenter, and initiates shutdown on all the VMware guests through a single Virtual Machine. This is a much …</p><p>Schneider Electric's <a href="http://www.se.com/en/product-range/61933-powerchute-network-shutdown/">PowerChute Network Shutdown</a> is a piece of software which communicates with your local UPS, and initiates system shutdown if the UPS battery is unable to continue providing power. This helps to preserve file integrity in the event of a prolonged power failure.</p>
<p>Previously, you had to install the PCNS client separately on each virtual machine. Since then though, APC have released a <a href="https://solutionexchange.vmware.com/store/products/apc-powerchute-network-shutdown-v4-1-for-vmware">PCNS VMware Appliance</a> which is installed directly into vCenter, and initiates shutdown on all the VMware guests through a single Virtual Machine. This is a much tidier model, so we've recently embarked on migrating to the PCNS Appliance.</p>
<p>After installing the PCNS 4.1 appliance and getting everything working, I discovered that the time on all the log files was wrong by a significant margin. I can't remember exactly what the margin was, it could have been say 8 hours or something.</p>
<p>I did a bit of research and eventually I discovered a spectaularly old question on the APC forums, dating all the way back to 2011:</p>
<p><em>"I have installed PCNS 2.2.4 into the vMA of an ESXi 4.1 server. It properly communicates with the associated NMC and performs correctly. However, it reports all the activities in Eastern Standard Time. I don't know where it's picking up that time zone and can't find anywhere to change it. In the vSphere client the time shows up correctly. Checking date inside the vMA from the CLI also shows the correct time and timezone. The date and time setting in the NMC is correct and is set to synch with NTP with correct time zone."</em><br>
From: <a href="http://forums.apc.com/spaces/7/ups-management-devices-powerchute-software/forums/general/6809/pcns-2-2-4-esxi-annoyance">http://forums.apc.com/spaces/7/ups-management-devices-powerchute-software/forums/general/6809/pcns-2-2-4-esxi-annoyance</a></p>
<p>The answers include a broken link to an APC web page about it, but fortunately the poster copied the original post detail, which showed me where to look:</p>
<p><em>"PCNS uses a standard java function to retrieve the current date from the system when writing events to the log. The Problem on the VIMA is that this function always returns the US date format (PDT).<br>
This is an issue with Java http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6456628<br>
You can correct the time issue on VIMA by modifying /etc/sysconfig/clock file.<br>
+/etc/sysconfig/clock contains a line ZONE="America/Los_Angeles"+<br>
You need to edit the ZONE= to match your region such as ZONE="America/New_York"</em></p>
<p>Sounds great! But when I looked in /etc/sysconfig/clock, I discovered my time zone was already set to "Pacific/Auckland".</p>
<p>However, it also contained the value "UTC = False". I changed this to "UTC = True", and et voilà! The problem is fixed!</p>Updating the modem and radio firmware on a Samsung Galaxy 5 (G900I)2016-10-27T00:00:00+13:002020-04-12T00:00:00+12:00Eric Lighttag:www.ericlight.com,2016-10-27:/updating-the-modem-and-radio-firmware-on-a-samsung-galaxy-5-g900i.html<p>A couple months ago, <a href="http://www.checkpoint.com">Check Point</a> revealed their discovery of the <a href="http://blog.checkpoint.com/2016/08/07/quadrooter/">Quadrooter vulnerability</a> affecting the Qualcomm chipsets in oodles of Android phones.</p>
<p>I use --CyanogenMod-- <a href="http://www.lineageos.org">LineageOS</a> on a Samsung Galaxy S5, so thankfully I <a href="https://web.archive.org/web/20161223020015/http://www.cyanogenmod.org/blog/cm-13-0-release-znh5y">received patches</a> for three of the four vulnerabilities in only a few days.</p>
<p>However, that last vulnerability was part of a proprietary binary blob for controlling the Qualcomm LTE chipset, only patchable by Samsung themselves. It took a while for the Samsung updates to roll out, and then I got distracted for a while, but I …</p><p>A couple months ago, <a href="http://www.checkpoint.com">Check Point</a> revealed their discovery of the <a href="http://blog.checkpoint.com/2016/08/07/quadrooter/">Quadrooter vulnerability</a> affecting the Qualcomm chipsets in oodles of Android phones.</p>
<p>I use --CyanogenMod-- <a href="http://www.lineageos.org">LineageOS</a> on a Samsung Galaxy S5, so thankfully I <a href="https://web.archive.org/web/20161223020015/http://www.cyanogenmod.org/blog/cm-13-0-release-znh5y">received patches</a> for three of the four vulnerabilities in only a few days.</p>
<p>However, that last vulnerability was part of a proprietary binary blob for controlling the Qualcomm LTE chipset, only patchable by Samsung themselves. It took a while for the Samsung updates to roll out, and then I got distracted for a while, but I finally downloaded my firmware. The package I've used is "G900IDVU1CPH3", which seems to be compatible at least with the three NZ-based carriers, as well as all the Australian carriers.</p>
<p>There are a couple little issues with the firmware upgrade, easily fixed if you know how. I'm going to assume you know exactly how to do everything without help. I'm sure you're pleased.</p>
<p>In particular, the version of Heimdall in the Debian Sid repositories (1.4.1-2) doesn't quite work with the SGS5. It appears <a href="https://www.google.com/search?q=ERROR%3A+Failed+to+send+request+to+end+PIT+file+transfer%21+samsung">other people</a> have had similar problems.</p>
<p>The beginning of fix for me came from <a href="https://github.com/turboyz">turboyz</a> on Github, at the bottom of this post: (Edit 2020-04-12: GitHub Issue 348 from <a href="https://github.com/Benjamin-Dobell/Heimdall/">https://github.com/Benjamin-Dobell/Heimdall/</a> has been deleted); however, he's manually made a couple changes to BridgeManager.cpp, which appear to be no longer necessary. We can simply build it from source:</p>
<div class="highlight"><pre><span></span><code><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="k">get</span> <span class="n">install</span> <span class="n">build</span><span class="o">-</span><span class="n">essential</span> <span class="n">cmake</span> <span class="n">zlib1g</span><span class="o">-</span><span class="n">dev</span> <span class="n">libusb</span><span class="o">-</span><span class="mi">1</span><span class="p">.</span><span class="mi">0</span><span class="o">-</span><span class="mi">0</span><span class="o">-</span><span class="n">dev</span> <span class="n">git</span>
<span class="n">git</span> <span class="n">clone</span> <span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">github</span><span class="p">.</span><span class="n">com</span><span class="o">/</span><span class="n">Benjamin</span><span class="o">-</span><span class="n">Dobell</span><span class="o">/</span><span class="n">Heimdall</span><span class="p">.</span><span class="n">git</span>
<span class="n">cd</span> <span class="n">Heimdall</span>
<span class="o">#</span> <span class="n">OPTIONAL</span><span class="p">:</span> <span class="n">Remove</span> <span class="n">the</span> <span class="o">`</span><span class="k">if</span><span class="p">(</span><span class="k">NOT</span> <span class="n">DISABLE_FRONTEND</span><span class="p">)</span><span class="o">`</span> <span class="n">codeblock</span> <span class="k">at</span> <span class="n">the</span> <span class="k">end</span> <span class="k">of</span> <span class="n">Heimdall</span><span class="o">/</span><span class="n">CMakeLists</span><span class="p">.</span><span class="n">txt</span>
<span class="o">#</span> <span class="n">I</span> <span class="n">believe</span> <span class="n">this</span> <span class="n">just</span> <span class="n">saves</span> <span class="k">time</span> <span class="n">compiling</span> <span class="n">the</span> <span class="n">GUI</span>
<span class="n">mkdir</span> <span class="n">build</span> <span class="o">&&</span> <span class="n">cd</span> <span class="n">build</span>
<span class="n">cmake</span> <span class="o">-</span><span class="n">DCMAKE_BUILD_TYPE</span><span class="o">=</span><span class="n">Release</span> <span class="p">..</span>
<span class="n">make</span>
<span class="n">cd</span> <span class="n">bin</span>
</code></pre></div>
<p>Now you've got a nice new Heimdall installation, with the approproate updates to allow it to talk nicely to the new Samsung bootloader.</p>
<p>I copied my new baseband files into the Heimdall/build/bin folder, just to get them all together. The last step is to flash your NON-HLOS.bin and modem.bin files:</p>
<div class="highlight"><pre><span></span><code><span class="err">./heimdall flash --APNHLOS NON-HLOS.bin --MODEM modem.bin</span>
</code></pre></div>
<p>I happen to have an issue on my phone currently where, even though the modem and LTE drivers have both been successfully installed, and even thought the Quadrooter tester is no longer showing any vulnerabilities, my Baseband version on my phone is still shown as the old one. I haven't been able to figure out why yet, but I don't think I'll worry about it for now. There have been reports that you should first do this with --no-reboot, wait for the update to complete, then pull your battery, then when you power back on, immediately go <em>back</em> into download mode and re-flash. Apparently this helps update the recognised Baseband version, but to be honest it didn't help me.</p>
<p>If you're completely 100% lucky and absolutely nothing goes wrong, you win! You should now have the most recent Samsung modem and LTE chipset drivers available for your phone... without having to roll back to the stock Samsung firmware.</p>
<p>Incidentally, if you want to save gigabytes and time downloading said firmware, and if your phone is precisely a Samsung Galaxy S5 (G900I), and if you definitely want firmware G900IDVU1CPH3, I've extracted the important files (modem.bin and NON-HLOS.bin) and stored them here:</p>
<p><a href="https://www.ericlight.com/files/G900IDVU1CPH3_modem_LTE.zip">https://www.ericlight.com/files/G900IDVU1CPH3_modem_LTE.zip</a><br>
SHA256 hash = a2ab13063583f6e83a3c2d8b79521a59ba103dda30a24bddf9248dd5a25bff3c </p>
<p>I promise I haven't intentionally backdoored them, but I make no warranties of any sort. They might just be pictures of my foot.</p>
<p>Good luck!</p>Using ECDSA certificates with Let's Encrypt2016-10-27T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2016-10-27:/using-ecdsa-certificates-with-lets-encrypt.html<p><a href="https://www.letsencrypt.org">Let's Encrypt</a>'s Certbot will generate an RSA key by default. But we want to step into the new and exciting world of elliptic curve cryptography! Unfortunately Certbot doesn't really roll that way, so there are a couple hoops to jump through first.</p>
<p>A word of caution: this post has been written in retrospect, some time after I actually got ECDSA working. That means there are bound to be squiggly little steps that I've missed, and I certainly should have provided screenshots or snippets that I've missed. Sorry.</p>
<p>This post …</p><p><a href="https://www.letsencrypt.org">Let's Encrypt</a>'s Certbot will generate an RSA key by default. But we want to step into the new and exciting world of elliptic curve cryptography! Unfortunately Certbot doesn't really roll that way, so there are a couple hoops to jump through first.</p>
<p>A word of caution: this post has been written in retrospect, some time after I actually got ECDSA working. That means there are bound to be squiggly little steps that I've missed, and I certainly should have provided screenshots or snippets that I've missed. Sorry.</p>
<p>This post assumes you've already installed Certbot. I had a working regular certificate from Certbot before I changed to ECDSA, so if you have problems following this from scratch, I do recommend trying that first.</p>
<p>For future reference, I'm running the latest certbot available in Debian unstable, which is version 0.8.1-3.</p>
<p>I got most of this information from <a href="https://scotthelme.co.uk/tag/lets-encrypt/">Scott Helme's website</a>, which has been awesome.</p>
<p>In brief:</p>
<p>1) Generate yourself an ECDSA private key:</p>
<div class="highlight"><pre><span></span><code><span class="err">openssl ecparam -genkey -name secp384r1 | openssl ec -out ec.key</span>
</code></pre></div>
<p>You can change the curve that you use, if you feel a bit wiggly about the <a href="http://blog.cr.yp.to/20140323-ecdsa.html">controversy around the NSA & NIST</a> degrading the quality of the curves. I don't feel particularly wiggly about that, myself.</p>
<p>2) Generate a Certificate Signing Request (CSR) with your shiny new key:</p>
<div class="highlight"><pre><span></span><code><span class="err">openssl req -new -sha256 -key ec.key -nodes -out ec.csr -outform pem</span>
</code></pre></div>
<p>That will give you ec.key (your private key), and ec.csr (your certificate signing request). Time to get Let's Encrypt involved.</p>
<p>3) Create your certificate:</p>
<div class="highlight"><pre><span></span><code><span class="err">certbot certonly -w /var/www/html/ -d {your_domain} --email "{your_email}" --csr ./ec.csr --agree-tos</span>
</code></pre></div>
<p>If everything goes perfectly, that should leave you with a new shiny set of certificates -- quite possibly named something clumsy like 0000-cert.pem and 0001-fullchain.pem, or similar. Throw those into your nginx config and give it a test to see if it's working.</p>
<p>4) Schedule your certificate renewals:</p>
<p>I had particular trouble with the renewal process of ECDSA certificates, because <code>certbot renew</code> isn't compatible with custom CSR's. You need to run <code>certbot certonly</code> to pass the --csr argument, and then you need to deal with the output yourself.</p>
<p>Even more irksome, the certonly function will fail if you ask it to renew certificates which already exist:</p>
<div class="highlight"><pre><span></span><code><span class="err">An unexpected error occurred:</span>
<span class="c">OSError: [Errno 17] File exists: '/etc/letsencrypt/live/{your_domain}/cert_ecdsa.pem'</span>
<span class="err">Please see the logfiles in /var/log/letsencrypt for more details.</span>
</code></pre></div>
<p>There doesn't seem to be any way to tell certbot to overwrite the old certificates automatically, so I created a /etc/letsencrypt/temp folder, and wrote up a really yuck cron job for it. If I were working on a production system I'd do something better, but this works for my lowly domain:</p>
<div class="highlight"><pre><span></span><code><span class="o">#</span> <span class="n">Recreate</span> <span class="n">certs</span> <span class="k">under</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">letsencrypt</span><span class="o">/</span><span class="n">temp</span>
<span class="mi">30</span> <span class="mi">2</span> <span class="mi">24</span> <span class="o">*</span> <span class="o">*</span> <span class="n">certbot</span> <span class="n">certonly</span> <span class="o">-</span><span class="n">w</span> <span class="o">/</span><span class="n">var</span><span class="o">/</span><span class="n">www</span><span class="o">/</span><span class="n">html</span><span class="o">/</span> <span class="o">-</span><span class="n">d</span> <span class="err">{</span><span class="n">your_domain</span><span class="err">}</span> <span class="c1">--email "{your_email}" --csr /path/to/your/ec.csr --agree-tos --non-interactive --webroot --cert-path /etc/letsencrypt/temp/cert_ecdsa.pem --fullchain-path /etc/letsencrypt/temp/fullchain_ecdsa.pem</span>
<span class="o">#</span> <span class="n">Backup</span> <span class="k">current</span> <span class="n">certs</span> <span class="k">to</span> <span class="n">home</span> <span class="n">dir</span>
<span class="mi">31</span> <span class="mi">2</span> <span class="mi">24</span> <span class="o">*</span> <span class="o">*</span> <span class="n">mv</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">letsencrypt</span><span class="o">/</span><span class="n">live</span><span class="o">/</span><span class="err">{</span><span class="n">your_domain</span><span class="err">}</span><span class="o">/</span><span class="n">cert_ecdsa</span><span class="p">.</span><span class="n">pem</span> <span class="o">~/</span><span class="n">certbackup</span><span class="o">/</span>
<span class="mi">31</span> <span class="mi">2</span> <span class="mi">24</span> <span class="o">*</span> <span class="o">*</span> <span class="n">mv</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">letsencrypt</span><span class="o">/</span><span class="n">live</span><span class="o">/</span><span class="err">{</span><span class="n">your_domain</span><span class="err">}</span><span class="o">/</span><span class="n">fullchain_ecdsa</span><span class="p">.</span><span class="n">pem</span> <span class="o">~/</span><span class="n">certbackup</span><span class="o">/</span>
<span class="o">#</span> <span class="k">Move</span> <span class="k">new</span> <span class="n">certs</span> <span class="k">to</span> <span class="n">live</span> <span class="n">folder</span>
<span class="mi">32</span> <span class="mi">2</span> <span class="mi">24</span> <span class="o">*</span> <span class="o">*</span> <span class="n">mv</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">letsencrypt</span><span class="o">/</span><span class="n">temp</span><span class="cm">/* /etc/letsencrypt/live/{your_domain}/</span>
<span class="cm"># Restart nginx</span>
<span class="cm">33 2 24 * * service nginx restart</span>
</code></pre></div>
<p>And that's all! It seems to be working so far, but I'm sure something is going to fail at some point -- maybe I'll hit my request limit, or the Let's Encrypt service will be down, and I'll lose my certs. If it happens too often I'll come up with a nicer cronjob and update this post.</p>Tidying up Pelican's URLs with the Flex theme2016-10-23T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2016-10-23:/tidying-up-pelicans-urls-with-the-flex-theme.html<p>This is just a brain-dump of tweaks I've made to my Pelican environment to get tidy URLs. In summary: One theme tweak, one Nginx tweak.</p>
<h2>Making the Flex Theme drop the ugly url#slug format:</h2>
<p>I've decided I'm going to roll with the <a href="https://github.com/alexandrevicenzi/Flex">Flex</a> theme for a while. I like it, but it had this habit of putting anchors and slugs into my article URLs.</p>
<p>For example, my first page is known to Pelican as "welcome-to-the-internet". However, links to the page were automatically created as "welcome-to-the-internet#welcome-to-the-internet". It seems redundant …</p><p>This is just a brain-dump of tweaks I've made to my Pelican environment to get tidy URLs. In summary: One theme tweak, one Nginx tweak.</p>
<h2>Making the Flex Theme drop the ugly url#slug format:</h2>
<p>I've decided I'm going to roll with the <a href="https://github.com/alexandrevicenzi/Flex">Flex</a> theme for a while. I like it, but it had this habit of putting anchors and slugs into my article URLs.</p>
<p>For example, my first page is known to Pelican as "welcome-to-the-internet". However, links to the page were automatically created as "welcome-to-the-internet#welcome-to-the-internet". It seems redundant. Also, it says the same thing twice. It repeats itself.</p>
<p>I discovered the issue in the Flex theme. It's under /templates/index.html, circa lines 7 and 29. Simply change:</p>
<div class="highlight"><pre><span></span><code><span class="cp">{{</span> <span class="nv">article.url</span> <span class="cp">}}</span><span class="x">#</span><span class="cp">{{</span> <span class="nv">article.slug</span> <span class="cp">}}</span><span class="x"></span>
</code></pre></div>
<p>... to... </p>
<div class="highlight"><pre><span></span><code><span class="cp">{{</span> <span class="nv">article.slug</span> <span class="cp">}}</span><span class="x"></span>
</code></pre></div>
<p>Fixed!</p>
<p>I haven't submitted a pull request to Alexandre, because I suspect it's intentional.</p>
<h2>Getting Nginx to serve tidy urls:</h2>
<p>By default, Pelican creates great urls like {server}/Ramblings/welcome-to-the-internet</p>
<p>This is great, but it CREATES files like /var/www/Ramblings/welcome-to-the-internet.html</p>
<p>Nginx by default doesn't see "welcome-to-the-internet" and automatically serve "welcome-to-the-internet.html". The lack of a file extention means that the .html file is fundamentally <em>a different file</em>, so it returns a handy-dandy 404 error instead.</p>
<p>To fix this, open /etc/nginx/sites-available/yoursite, and find:</p>
<div class="highlight"><pre><span></span><code><span class="err">location / {</span>
<span class="err"> try_files $uri $uri/ =404;</span>
<span class="err">}</span>
</code></pre></div>
<p>Change it to the following - note I've added $uri.htm and $uri.html, to inform Nginx that it should try appending .htm or .html onto the end of a uri if it can't find the page:</p>
<div class="highlight"><pre><span></span><code><span class="err">location / {</span>
<span class="err"> try_files $uri.htm $uri.html $uri =404;</span>
<span class="err">}</span>
</code></pre></div>
<p>All done, happy tidy URLs!</p>Alfredo Sauce2016-10-22T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2016-10-22:/alfredo-sauce.html<p>I had the urge to make a homemade alfredo the other night. I found a recipe called <a href="http://www.food.com/recipe/better-than-olive-garden-alfredo-sauce-141983">"Better than Olive Garden Alfredo Sauce"</a>, which is pretty descriptive, I guess. I made a couple tweaks here and there, though.</p>
<p>I usually stray wildly from recipies whenever I decide to follow one, but having not made an alfredo sauce before, I largely stuck to the guide. A couple changes I did make, though:</p>
<ul>
<li>Instead of adding the garlic and cream together, I heated the butter and <em>fried</em> the garlic to bring out …</li></ul><p>I had the urge to make a homemade alfredo the other night. I found a recipe called <a href="http://www.food.com/recipe/better-than-olive-garden-alfredo-sauce-141983">"Better than Olive Garden Alfredo Sauce"</a>, which is pretty descriptive, I guess. I made a couple tweaks here and there, though.</p>
<p>I usually stray wildly from recipies whenever I decide to follow one, but having not made an alfredo sauce before, I largely stuck to the guide. A couple changes I did make, though:</p>
<ul>
<li>Instead of adding the garlic and cream together, I heated the butter and <em>fried</em> the garlic to bring out a bit more flavour</li>
<li>I also fried a goodly dose of smoked bacon along with the garlic. Bacon first, of course, so the garlic doesn't burn</li>
<li>The recipe reckoned we should use two garlic cloves. Ha! Four, definitely.</li>
<li>I also added some chopped spring onion and a pinch of cayenne pepper</li>
</ul>
<p>I've reproduced the origina recipe, along with my changes, here:</p>
<h2>Ingredients</h2>
<ul>
<li>3 tablespoons butter</li>
<li>2 tablespoons olive oil</li>
<li>2 or 3 rashers of bacon, chopped into squares</li>
<li>4 garlic cloves, minced</li>
<li>1 chopped spring onion</li>
<li>2 cups cream</li>
<li>1⁄4 teaspoon freshly-ground pepper</li>
<li>1 pinch cayenne pepper</li>
<li>1⁄2 cup grated parmesan cheese</li>
<li>3⁄4 cup mozzarella cheese</li>
<li>1 1/2 supermarket tubes of fettucini pasta</li>
</ul>
<h2>Method</h2>
<p>Melt butter in medium saucepan with olive oil over medium/low heat.<br>
Fry the bacon until until browned.<br>
Add the garlic, fry until the garlic starts to brown.<br>
Add cream and spring onion; bring mixture to a simmer.<br>
Stir often.<br>
Add the Parmesan cheese and simmer sauce for 8-10 minutes or until sauce has thickened and is smooth.<br>
When sauce has thickened add the Mozzarella cheese and stir until smooth. STIR FREQUENTLY.<br>
Add the pepper and cayenne.<br>
While the sauce cooks, boil noodles for 3-5 minutes.<br>
Place pasta on serving plates and spoon sauce over pasta. </p>
<p><a href="http://imgur.com/gallery/pGwVS">Bone app the teeth!</a></p>
<p>(Alright, most of the reason for this blog post is for me to practice my <a href="https://daringfireball.net/projects/markdown/syntax">Markdown</a> skills)</p>Welcome to the Internet2016-10-15T00:00:00+13:002020-11-24T21:28:24+13:00Eric Lighttag:www.ericlight.com,2016-10-15:/welcome-to-the-internet.html<p>Well, I'm finally here.</p>
<p>I've never <em>really</em> run a blog before... I did write a bunch of stuff back when I ran Gravity Computing; it just was never really "bloggy". That content has now been moved to <a href="http://www.efficientsoftware.co.nz/blog/">Efficient Software</a>, but I'll probably copy my parts back over here when time permits.</p>
<p>I really have no intention of running a blog, but I <strong>do</strong> come across interesting and challenging problems <em>all the time</em>, which I'd like to share with people who are, apparently, just like you.</p>
<p>I've got a couple things …</p><p>Well, I'm finally here.</p>
<p>I've never <em>really</em> run a blog before... I did write a bunch of stuff back when I ran Gravity Computing; it just was never really "bloggy". That content has now been moved to <a href="http://www.efficientsoftware.co.nz/blog/">Efficient Software</a>, but I'll probably copy my parts back over here when time permits.</p>
<p>I really have no intention of running a blog, but I <strong>do</strong> come across interesting and challenging problems <em>all the time</em>, which I'd like to share with people who are, apparently, just like you.</p>
<p>I've got a couple things saved up that I want to post about in the next few days, but heck this site could languish for months at a time -- so feel free to add it to your reader, I definitely won't fill your feed.</p>