I’ve been trying to get my Huawei E3276-150 4G/LTE USB modem to work with my PC Engines APU2 router board for quite a while. Once connected, the Huawei modem creates its own network thanks to its HiLink mode and is detected as an Ethernet over USB device in Linux. All I have to do is to ask the modem’s DHCP server for an IP address, use the modem as the default gateway and I should be all set. Right? Continue reading
PC Engines APU1 vs APU2 UnixBench benchmark
Best budget Linux laptop 2016
Recently, I’ve replaced my five year old 13″ MacBook Air with a new budget Linux laptop. Since I’ve been using Linux desktops more and more there was just no point in buying another Apple product. The time was ripe to go fully Linux on my to-go laptop.
When I started evaluating laptops I quickly realized that even in 2016 it’s still nearly impossible to buy a new laptop with full Linux driver support. Linux and mobile hardware support is somewhat like a good red wine, it gets better over time. One notable exception is the Dell XPS 13 Developer Edition which comes with a preloaded Ubuntu Desktop operating system. I’m not sure if Dell still sells an updated version of the Developer Edition model but it was not available in my country and I didn’t want to shell out more than $800 for my new laptop anyway.
Best budget Linux laptop
When it comes to portable computers, I’m probably kinda old-school. I don’t need a touch screen (fingerprints everywhere, eeek!) or some funky 2-in-1 tablet/laptop convertible like the Dell Yoga. Just a slim, lightweight 13″ laptop with a nice display (preferably matte), a battery-friendly processor, flash-based storage and a couple of full-size USB 3.0 ports for a decent price. After looking at a half dozen or so potential candidates I’ve set my eyes on the ASUS Zenbook UX305CA with the 6th gen. Intel Skylake mobile processor.
How to compile Quagga with SNMP support
Since the default Quagga package in Ubuntu doesn’t have SNMP support enabled, the Quagga package has to be compiled locally. The following instructions may work for Debian as well but I only tested it in Ubuntu Server 14.04 LTS.
Now, edit /etc/quagga/daemons
and enable at least zebra
and bgpd
and let’s create some empty config files for Quagga:
touch /etc/quagga/bgpd.conf ; touch /etc/quagga/zebra.conf
To enable SNMP support in Quagga, the line agentx
has to be inserted into bgpd.conf
and zebra.conf
:
drfalken@wopr:/etc/quagga# head bgpd.conf
hostname AS65535
log file /var/log/quagga/bgpd.log
agentx
debug bgp events
debug bgp filters
debug bgp updates
router bgp 65535
bgp router-id 1.2.3.4
…
I wont dwelve into how to setup the SNMP daemon but don’t forget to add the following lines to the snmpd.conf
configuration file and restart the SNMP daemon afterwards:
master agentx
agentxsocket /var/agentx/master
agentxperms 777 777
Make sure to set proper permissions for the agentx directory with a
chmod 755 /var/agentx/
or you will get error messages like snmp[warning]: Warning: Failed to connect to the agentx master agent ([NIL])
Once Quagga is able to connect to the local SNMP daemon, a message like this will show up in Quagga’s log file:
snmp[info]: NET-SNMP version 5.7.2 AgentX subagent connected
Monitoring Quagga BGP sessions using SNMP
Monitoring BGP sessions works fantastically using LibreNMS. You can chose to receive push notifications and/or emails if a BGP session goes down/up or is flapping. However, there’s some tinkering involved to display 32-bit ASNs properly in LibreNMS (let me know in the comments if you’re interested) because the MIB only handles 16-bit integers. Unfortunately, there’s no IPv6 support in Quagga’s current SNMP implementation as well.
Waking up a NAS from OS X at boot time using Wake-on-LAN (WOL)
Since OS X 10.11 El Capitan protects certain system directories from modifications, my NASwake solution to wake a NAS once the Mac starts up published back in 2010 is no longer working.
I decided against building another .pkg installer since it requires root permissions and I also prefer using Homebrew instead of some obscure binary for sending the magic WOL packet. Here are the four steps to start your Wake-on-Lan-capable NAS once your Mac starts up:
- Install “Homebrew” (required for the wakeonlan script)
- Install the wakeonlan script using the Homebrew package manager
- Save the naswake plist to /Library/LaunchDaemons
- Save the naswake shell script to /usr/local/bin and set your NAS’s MAC-address
1. Install Homebrew
See http://brew.sh for instructions. Once installed, check with brew doctor
if Homebrew was installed properly.
2. Install the wakeonlan script using the Homebrew package manager
brew install wakeonlan
This will install the wakeonlan Perl script. See man wakeonlan
for details.
3. Save the naswake plist to /Library/LaunchDaemons
sudo nano /Library/LaunchDaemons/com.trick77.wol2.plist
Paste the XML below into the editor.
4. Save the naswake shell script to /usr/local/bin
sudo nano /usr/local/bin/naswake.sh
sudo chmod +x /usr/local/bin/naswake.sh
Paste the script below into the editor. Don’t forget to set your NAS’ MAC address in the last line of the script!
That’s it! Make sure WOL is enabled in the NAS.
Tips & tricks for the PC Engines APU
Being somewhat addicted to Linux mini computers, I just had to lay my hands on a PC Engines APU. A lot of information about the APU is strewn all over the Internet so I wanted to consolidate it all in one single post.
Installing Ubuntu Server using the serial console
To boot the Ubuntu Server installer using the serial console, some startup config files have to be modified. See this post for instructions.
On the Mac, I’m using serial. It already contains the drivers for my PL2303 based USB serial adapter. As a free alternative, Prolific’s PL2303 OS X drivers work pretty well together with minicom
from the brew project. If output is being displayed with minicom but input doesn’t work, make sure to turn off hardware flow control. The screen command may work as well.
Show network devices as eth0, eth1, eth2 instead of p4p1, p4p2, p4p3
Edit /etc/default/grub
as follows:
GRUB_CMDLINE_LINUX_DEFAULT="biosdevname=0"
Update grub configuration
# update-grub
and
# reboot
Don’t forget to update /etc/network/interfaces
accordingly.
Show output during boot
Edit /etc/default/grub
as follows:
GRUB_CMDLINE_LINUX="console=tty0 console=ttyS0,115200n8" GRUB_TERMINAL=serial GRUB_SERIAL_COMMAND="serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1"
Update grub configuration
# update-grub
and
# reboot
Enable NMI Watchdog
# modprobe sp5100_tco && echo "sp5100_tco" >> /etc/modules
Enable temperatur sensor
apt-get install lm-sensors
# sensors k10temp-pci-00c3 Adapter: PCI adapter temp1: +52.0°C (high = +70.0°C) (crit = +100.0°C, hyst = +97.0°C)
Enable LEDs and reboot button
Check out the apu-led-button repository on Github.
Use max. cpufreq
Ubuntu will always set the CPU governor to ondemand during boot.
# cat /proc/cpuinfo vendor_id : AuthenticAMD model name : AMD G-T40E Processor cpu MHz : 800.000
For the APU this means the CPU will be run at 800 MHz instead of 1 GHz. If you prefer the CPU to run at full speed at all times:
# wget -O /usr/local/sbin https://gist.githubusercontent.com/trick77/21cfc65c769609be29e2/raw/076e21c7b844a9eeb67ca4184544ec27d11164f7/gov
Insert into /etc/rc.local
just above exit 0
:
/usr/local/sbin/gov performance
Or as an alternative, just disable the Ubuntu ondemand init script from the command line:
# update-rc.d ondemand disable
# cat /proc/cpuinfo vendor_id : AuthenticAMD model name : AMD G-T40E Processor cpu MHz : 1000.000
Enable beep
apt-get install beep modprobe pcspkr && echo pcspkr >> /etc/modules
Comment pcspkr
in /etc/modprobe.d/blacklist.conf
to unblacklist the module.
Imperial March:
beep -l 350 -f 392 -D 100 -n -l 350 -f 392 -D 100 -n -l 350 -f 392 -D 100 -n -l 250 -f 311.1 -D 100 -n -l 25 -f 466.2 -D 100 -n -l 350 -f 392 -D 100 -n -l 250 -f 311.1 -D 100 -n -l 25 -f 466.2 -D 100 -n -l 700 -f 392 -D 100 -n -l 350 -f 587.32 -D 100 -n -l 350 -f 587.32 -D 100 -n -l 350 -f 587.32 -D 100 -n -l 250 -f 622.26 -D 100 -n -l 25 -f 466.2 -D 100 -n -l 350 -f 369.99 -D 100 -n -l 250 -f 311.1 -D 100 -n -l 25 -f 466.2 -D 100 -n -l 700 -f 392 -D 100 -n -l 350 -f 784 -D 100 -n -l 250 -f 392 -D 100 -n -l 25 -f 392 -D 100 -n -l 350 -f 784 -D 100 -n -l 250 -f 739.98 -D 100 -n -l 25 -f 698.46 -D 100 -n -l 25 -f 659.26 -D 100 -n -l 25 -f 622.26 -D 100 -n -l 50 -f 659.26 -D 400 -n -l 25 -f 415.3 -D 200 -n -l 350 -f 554.36 -D 100 -n -l 250 -f 523.25 -D 100 -n -l 25 -f 493.88 -D 100 -n -l 25 -f 466.16 -D 100 -n -l 25 -f 440 -D 100 -n -l 50 -f 466.16 -D 400 -n -l 25 -f 311.13 -D 200 -n -l 350 -f 369.99 -D 100 -n -l 250 -f 311.13 -D 100 -n -l 25 -f 392 -D 100 -n -l 350 -f 466.16 -D 100 -n -l 250 -f 392 -D 100 -n -l 25 -f 466.16 -D 100 -n -l 700 -f 587.32 -D 100 -n -l 350 -f 784 -D 100 -n -l 250 -f 392 -D 100 -n -l 25 -f 392 -D 100 -n -l 350 -f 784 -D 100 -n -l 250 -f 739.98 -D 100 -n -l 25 -f 698.46 -D 100 -n -l 25 -f 659.26 -D 100 -n -l 25 -f 622.26 -D 100 -n -l 50 -f 659.26 -D 400 -n -l 25 -f 415.3 -D 200 -n -l 350 -f 554.36 -D 100 -n -l 250 -f 523.25 -D 100 -n -l 25 -f 493.88 -D 100 -n -l 25 -f 466.16 -D 100 -n -l 25 -f 440 -D 100 -n -l 50 -f 466.16 -D 400 -n -l 25 -f 311.13 -D 200 -n -l 350 -f 392 -D 100 -n -l 250 -f 311.13 -D 100 -n -l 25 -f 466.16 -D 100 -n -l 300 -f 392.00 -D 150 -n -l 250 -f 311.13 -D 100 -n -l 25 -f 466.16 -D 100 -n -l 700 -f 392
How to receive Cymru’s IPv6 Bogon list using Quagga
The provided BGP sample configuration for Quagga on Cymru’s web site didn’t work for me. Since my AS is IPv6-only, I’m only interested in the IPv6 Bogon feed. Here’s an excerpt from my Quagga bgpd.conf
:
router bgp aut-num bgp router-id id bgp log-neighbor-changes no bgp default ipv4-unicast neighbor cymru-bogon peer-group neighbor cymru-bogon remote-as 65332 neighbor cymru-bogon timers 3600 10800 neighbor cymru-bogon description AS65332 Cymru FullBogon Feed neighbor cymru-bogon ebgp-multihop 255 neighbor cymru-bogon password changeme neighbor cymru-bogon activate neighbor cymru-bogon prefix-list pl-cymru-ipv4-in in neighbor cymru-bogon prefix-list pl-cymru-out out neighbor 38.xx.xx.xx peer-group cymru-bogon neighbor 193.xx.xx.xx peer-group cymru-bogon address-family ipv6 neighbor cymru-bogon activate neighbor cymru-bogon soft-reconfiguration inbound neighbor cymru-bogon route-map rm-cymru-ipv6-in in neighbor cymru-bogon prefix-list pl-cymru-ipv6-out out neighbor 38.xx.xx.xx peer-group cymru-bogon neighbor 193.xx.xx.xx peer-group cymru-bogon exit-address-family ip prefix-list pl-cymru-ipv4-in seq 5 deny any ip prefix-list pl-cymru-out seq 5 deny any ipv6 prefix-list pl-cymru-ipv6-out seq 5 deny any ip community-list 10 permit 65332:888 route-map rm-cymru-ipv6-in permit 10 match community 10 set ip next-hop 192.0.2.1 set ipv6 next-hop global 100::dead:beef:1
Since Zebra
won’t install routes learned over BGP that are not routable, I also needed to make sure that 100::dead:beef:1
is (null-)routed. My solution was to install a Cisco-style Null0 interface in /etc/network/interfaces
:
# blackhole iface Null0 inet manual pre-up ip link add dev Null0 type dummy pre-up ip link set Null0 up up ip -6 route add 100::/64 dev Null0 proto static metric 255 up ip -4 route add 192.0.2.1/32 dev Null0 proto static metric 255 down ip link del dev Null0
By the way, that 100::/64 I’m using to null-route is a designated (RFC6666) IPv6 discard-only address block.
Once the BGP session is up, only IPv6 routes will be learned from Cymru’s bogon feed. I’m using IPv4 transport for the BGP session but it should work using IPv6 transport as well.
BGP neighbor is 38.xx.xx.xx, remote AS 65332, local AS xxxxx, external link Member of peer-group cymru-bogon for session parameters BGP version 4, remote router ID 38.xx.xx.xx BGP state = Established, up for 18:52:18 Last read 00:11:49, hold time is 10800, keepalive interval is 3600 seconds Configured hold time is 10800, keepalive interval is 3600 seconds Neighbor capabilities: 4 Byte AS: advertised and received Route refresh: advertised and received(old & new) Address family IPv4 Unicast: advertised and received Address family IPv6 Unicast: advertised and received Message statistics: Inq depth is 0 Outq depth is 0 Sent Rcvd Opens: 1 1 Notifications: 0 0 Updates: 0 118 Keepalives: 20 19 Route Refresh: 0 0 Capability: 0 0 Total: 21 138 Minimum time between advertisement runs is 30 seconds For address family: IPv4 Unicast cymru-bogon peer-group member AF-dependant capabilities: Outbound Route Filter (ORF) type (128) Prefix-list: Send-mode: received Community attribute sent to this neighbor(both) Inbound path policy configured Outbound path policy configured Incoming update prefix filter list is *pl-cymru-ipv4-in Outgoing update prefix filter list is *pl-cymru-out 0 accepted prefixes For address family: IPv6 Unicast cymru-bogon peer-group member Inbound soft reconfiguration allowed Community attribute sent to this neighbor(both) Inbound path policy configured Outbound path policy configured Outgoing update prefix filter list is *pl-cymru-ipv6-out Route map for incoming advertisements is *rm-cymru-ipv6-in 60088 accepted prefixes Connections established 1; dropped 0 Last reset never External BGP neighbor may be up to 255 hops away. Local host: 185.xx.xx.xx, Local port: 59623 Foreign host: 38.xx.xx.xx, Foreign port: 179 Nexthop: 185.xx.xx.xx Nexthop global: 2001:xxxx:xxxx:: Nexthop local: fe80::225:xxxx:xxxx:xxxx BGP connection: non shared network Read thread: on Write thread: off
Setting up a Huawei E3276-150 4G/LTE USB modem on Ubuntu Server/Desktop
I just received an unlocked Huawei E3276s-150 4G/LTE USB modem/surfstick I bought on eBay the other day. I went for the E3276s-150 because the 150 seemed to be the most compatible option for European 4G mobile networks. There are even cheaper Huawei E3276 models like the E3276-920 which you can buy for less than 20 bucks. However, the 920 seems to be frequency-optimized for Asian mobile networks and may not perform as well as a E3276s-150 in Western Europe.
To my great surprise, setting up the Huawei E3276 on Ubuntu 15.04 Desktop was literally plug & play. After a few seconds after plugging it in, I was greeted with a “Connection Established” message. Nicely done, Canonical!
On Ubuntu Server, like most Huawei modems, the stick is recognised as a memory card reader. It has to be switched to a USB modem device first using the usb_modeswitch
command in order to establish a mobile network connection. If it’s not already installed, usb_modeswitch
can be installed using apt-get -y install usb-modeswitch
.
Memory card reader mode:
drfalken@wopr:~# lsusb Bus 001 Device 007: ID 12d1:1f01 Huawei Technologies Co., Ltd.
To turn the E3276 into a modem:
drfalken@wopr:~# usb_modeswitch -v 12d1 -p 1f01 -M '55534243123456780000000000000011062000000101000100000000000000'
If the change was successful, lsusb
shows a different USB product id now:
drfalken@wopr:~# lsusb Bus 001 Device 007: ID 12d1:14db Huawei Technologies Co., Ltd.
At the same time, dmesg
should output something like this:
drfalken@wopr:~# dmesg -T [Fri May 29 20:55:41 2015] usb 1-1: New USB device found, idVendor=12d1, idProduct=14db [Fri May 29 20:55:41 2015] usb 1-1: New USB device strings: Mfr=2, Product=1, SerialNumber=0 [Fri May 29 20:55:41 2015] usb 1-1: Product: HUAWEI Mobile [Fri May 29 20:55:41 2015] usb 1-1: Manufacturer: HUAWEI Technology [Fri May 29 20:55:41 2015] cdc_ether 1-1:1.0 eth1: register 'cdc_ether' at usb-0000:00:14.0-1, CDC Ethernet Device, 57:2d:70:33:22:10
Since the modem registered itself on eth1 (the name depends on the number of network devices, it doesn’t HAVE to be on eth1), we now simply fetch an IP address from the modem using:
drfalken@wopr:~# dhclient -v eth1 Internet Systems Consortium DHCP Client 4.2.4 Copyright 2004-2012 Internet Systems Consortium. All rights reserved. For info, please visit https://www.isc.org/software/dhcp/ Listening on LPF/eth1/57:2d:70:33:22:10 Sending on LPF/eth1/57:2d:70:33:22:10 Sending on Socket/fallback DHCPDISCOVER on eth1 to 255.255.255.255 port 67 interval 3 (xid=0x3b73326b) DHCPREQUEST of 192.168.1.100 on eth1 to 255.255.255.255 port 67 (xid=0x3b73326b) DHCPOFFER of 192.168.1.100 from 192.168.1.1 DHCPACK of 192.168.1.100 from 192.168.1.1 bound to 192.168.1.100 -- renewal in 36557 seconds.
Yay, the modem has made itself available on 192.168.1.100 (it even has a web interface on port 80) with a /24 prefix and a gateway at 192.168.1.1.
By the way, make sure none of your local networks use 192.168.1.0/24 or it will collide with the Huawei’s local network.
Depending on a few factors dhclient
may or may not have changed the default gateway. If the default gateway points to the modem, it will be at 192.168.1.1 on eth1:
drfalken@wopr:~# ip route show | grep default default via 192.168.1.1 dev eth1
If this is not the case, you may have to remove the existing default gateway and replace it using:
drfalken@wopr:~# ip route del default ; ip route add default via 192.168.1.1
And… connected!
drfalken@wopr:~# ping 8.8.8.8 PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. 64 bytes from 8.8.8.8: icmp_seq=1 ttl=57 time=22.7 ms 64 bytes from 8.8.8.8: icmp_seq=2 ttl=57 time=34.9 ms 64 bytes from 8.8.8.8: icmp_seq=3 ttl=57 time=39.7 ms
Make sure /etc/resolv.conf
contains a valid nameserver if you can’t resolve domain names.
To switch the Huawei E3276 into a modem at boot time, create /etc/udev/rules.d/70-usb-modeswitch.rules
and insert this line:
ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1f01", RUN+="/usr/sbin/usb_modeswitch -v 12d1 -p 1f01 -M '55534243123456780000000000000011062000000101000100000000000000'"
To automatically add a valid nameserver in /etc/resolv.conf
when eth1 comes up, add these lines to /etc/dhcp/dhclient.conf
:
interface "eth1" { prepend domain-name-servers 8.8.8.8; request subnet-mask, broadcast-address, time-offset, routers, domain-name, domain-name-servers, domain-search, host-name, dhcp6.name-servers, dhcp6.domain-search, netbios-name-servers, netbios-scope, interface-mtu, rfc3442-classless-static-routes, ntp-servers, dhcp6.fqdn, dhcp6.sntp-servers; require routers, domain-name-servers; }
If you don’t want to run dhclient
manually, you can either add an eth1 dhcp section in /etc/network/interfaces
or add the dhclient eth1
command to /etc/rc.local
.
Just FYI: I’ve been using Vivid Vervet’s (Ubuntu 15.04) 3.19 kernel in Ubuntu Server 14.04 LTS. Vivid’s newer kernel can be installed using apt-get install linux-image-generic-lts-vivid
. Not sure if it makes a difference compared to 14.04’s default kernel though.
Dockerflix: Docker-based SNI proxy for watching U.S. Netflix, Hulu, MTV, Vevo, Crackle, ABC, NBC, PBS…
Recently, I published a new project on Github called Dockerflix. Instead of HAProxy, Dockerflix uses sniproxy. To make the installation a breeze, I boxed the proxy into a Docker container and wrote a small, Python-based Dnsmasq configuration generator. And voilà: DNS-unblocking as a service (DAAS) ;-)
Thanks to sniproxy’s ability to proxy requests based on a wildcard/regex match it’s now so much easier to add support for a service. Now it’s usually enough to just add the main domain name to the proxy and DNS configuration and Dockerflix will be able to hop the geo-fence in most cases. Since most on-demand streaming media providers are using an off-domain CDN for the video stream, only web site traffic gets sent through Dockerflix. A few exceptions may apply though, notably if the video stream itself is geo-fenced.
Dockerflix only handles requests using plain HTTP or TLS using the SNI extension. Some media players don’t support SNI and thus won’t work with Dockerflix.
If you need to proxy plain old SSLv1/v2 for a device, have a look at the non-SNI approach shown in tunlr-style-dns-unblocking.
A few media players (i.e. Chromecast) ignore your DNS settings and always resort to a pre-configured DNS resolver which can’t be changed (it still can be done though by rerouting these requests using iptables).
Check it out: https://github.com/trick77/dockerflix
How to encrypt an ODROID-C1’s Ubuntu root filesystem with DM-crypt LUKS
The starting point is a running ORDOID-C1 with the Ubuntu minimal image. Make sure the Ubuntu installation has been dist-upgraded and to use the latest linux-image-c1 kernel image available (3.10.72-78 as of this writing). The ODROID-C1 has to be running the lastest kernel available, check with uname -r
. Some of the early Ubuntu minimal images may suffer from a dist-upgrade problem, see here how to fix it. I’m using an 8 GB eMMC card but if you change the /dev ids throughout the installation process, it may work with an SD-card too.
root@c1:/# apt-get -y install lvm2 cryptsetup parted nano rsync
Since we can’t convert a running root partition, we’re going to add a 3rd partition which will be our encrypted root filesystem. Check with parted -l
where the 2nd partition ends because we’re going to add the new partition right there.
root@c1:~# parted -l
Model: MMC 008G92 (sd/mmc)
Disk /dev/mmcblk0: 7818MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Number Start End Size Type File system Flags
1 1049kB 135MB 134MB primary fat16 lba
2 135MB 4295MB 4160MB primary ext4
In this case, the 2nd partition ends at 4295MB, which will be the starting value for the new partition.
root@c1:~# parted
(parted) mkpart primary ext4
Start? 4295MB
END? 100%
q
Now we’re going to tag the new partition for LVM:
root@c1:~# fdisk /dev/mmcblk0
Command (m for help): t
Partition number (1-4): 3
Hex code (type L to list codes): 8e
Command (m for help): w
The next step is to setup LVM and to encrypt our new root partition. I’m going to name the physical volume (PV) lvm, the volume group vg and the logical root volume root.
root@c1:~# cryptsetup -c aes-xts-plain -y -s 512 luksFormat /dev/mmcblk0p3
root@c1:~# cryptsetup luksOpen /dev/mmcblk0p3 lvm
root@c1:~# pvcreate /dev/mapper/lvm
root@c1:~# vgcreate vg /dev/mapper/lvm
root@c1:~# lvcreate -l 100%FREE -n root vg
root@c1:~# mkfs.ext4 /dev/mapper/vg-root
Let’s try to mount the new, encrypted root volume:
root@c1:~# mount /dev/mapper/vg-root /mnt
Copy the existing root volume to the new, enrypted root volume:
root@c1:~# rsync -av --exclude=/media --exclude=/mnt --exclude=/proc --exclude=/dev --exclude=/sys / /mnt
These are the commands to chroot our new root volume from the old root partition. You can always use them to gain access to the encrypted root volume from the old root partition.
mkdir -p /mnt/dev
mkdir -p /mnt/mnt
mkdir -p /mnt/proc
mkdir -p /mnt/sys
mkdir -p /mnt/media
cryptsetup luksOpen /dev/mmcblk0p3 lvm
mount /dev/mapper/vg-root /mnt
mount -o rbind /dev /mnt/dev
mount -t proc proc /mnt/proc
mount -t sysfs sys /mnt/sys
mount -t vfat /dev/mmcblk0p1 /mnt/media
chroot /mnt
The following actions take place in the chrooted environment on the new, encrypted root LV. Make sure you don’t modify the existing root partition!
Register the encrypted volume in /etc/crypttab:
echo lvm UUID=$(cryptsetup luksUUID /dev/mmcblk0p3) none luks|tee /etc/crypttab
Add a line in /etc/fstab
for the root volume:
/dev/mapper/vg-root / ext4 errors=remount-ro 0 1
Being chrooted to the encrypted volume, we can now regenerate the initrd.img using
root@c1:~# update-initramfs -u -k $(uname -r)
Since support for dm-crypt has already been built into the kernel of the minimal image, we don’t have to add any crypto-modules to /etc/initramfs-tools/modules/
. initramfs also does a pretty good job (thanks to the MODULES=most
setting) determining what to add for lvm and dm-crypt support. Just to make sure, let’s have a look what has been placed into the new initrd.img:
root@c1:~# lsinitramfs /boot/initrd.img-$(uname -r) | grep crypt
sbin/cryptsetup
conf/conf.d/cryptroot
scripts/local-top/cryptopensc
scripts/local-top/cryptroot
scripts/local-bottom/cryptopensc
lib/libcryptsetup.so.4
lib/modules/3.10.72-78/kernel/arch/arm/crypto
lib/modules/3.10.72-78/kernel/arch/arm/crypto/aes-arm.ko
lib/modules/3.10.72-78/kernel/crypto
lib/modules/3.10.72-78/kernel/crypto/rmd160.ko
lib/modules/3.10.72-78/kernel/crypto/seed.ko
lib/modules/3.10.72-78/kernel/crypto/michael_mic.ko
lib/modules/3.10.72-78/kernel/crypto/rmd320.ko
lib/modules/3.10.72-78/kernel/crypto/cast6_generic.ko
lib/modules/3.10.72-78/kernel/crypto/rmd128.ko
lib/modules/3.10.72-78/kernel/crypto/rmd256.ko
lib/modules/3.10.72-78/kernel/crypto/lzo.ko
lib/modules/3.10.72-78/kernel/crypto/blowfish_generic.ko
lib/modules/3.10.72-78/kernel/crypto/khazad.ko
lib/modules/3.10.72-78/kernel/crypto/serpent_generic.ko
lib/modules/3.10.72-78/kernel/crypto/fcrypt.ko
lib/modules/3.10.72-78/kernel/crypto/camellia_generic.ko
lib/modules/3.10.72-78/kernel/crypto/twofish_generic.ko
lib/modules/3.10.72-78/kernel/crypto/async_tx
lib/modules/3.10.72-78/kernel/crypto/async_tx/async_tx.ko
lib/modules/3.10.72-78/kernel/crypto/async_tx/async_pq.ko
lib/modules/3.10.72-78/kernel/crypto/async_tx/async_raid6_recov.ko
lib/modules/3.10.72-78/kernel/crypto/async_tx/async_xor.ko
lib/modules/3.10.72-78/kernel/crypto/async_tx/async_memcpy.ko
lib/modules/3.10.72-78/kernel/crypto/cast5_generic.ko
lib/modules/3.10.72-78/kernel/crypto/tea.ko
lib/modules/3.10.72-78/kernel/crypto/xts.ko
lib/modules/3.10.72-78/kernel/crypto/xor.ko
lib/modules/3.10.72-78/kernel/crypto/ansi_cprng.ko
lib/modules/3.10.72-78/kernel/crypto/wp512.ko
lib/modules/3.10.72-78/kernel/crypto/cast_common.ko
lib/modules/3.10.72-78/kernel/crypto/tgr192.ko
lib/modules/3.10.72-78/kernel/crypto/zlib.ko
lib/modules/3.10.72-78/kernel/crypto/lrw.ko
lib/modules/3.10.72-78/kernel/crypto/anubis.ko
lib/modules/3.10.72-78/kernel/crypto/blowfish_common.ko
lib/modules/3.10.72-78/kernel/crypto/sha512_generic.ko
lib/modules/3.10.72-78/kernel/crypto/twofish_common.ko
lib/modules/3.10.72-78/kernel/crypto/salsa20_generic.ko
lib/modules/3.10.72-78/kernel/crypto/gf128mul.ko
lib/cryptsetup
lib/cryptsetup/askpass
lib/arm-linux-gnueabihf/libgcrypt.so.11
Looking good, the scripts/local-top/cryptroot
script is now part of initrd.img. It will be called during the first phase of the Linux boot and ask for the root volume passphrase once initramfs is executed.
To update the uInitrd file in the FAT32 boot partition we first have to recreate the image using the new initrd.img containing lvm and crypto support:
root@c1:~# mkimage -A arm -O linux -T ramdisk -C none -a 0 -e 0 -n "uInitrd $(uname -r)" -d /boot/initrd.img-$(uname -r) /tmp/uInitrd-$(uname -r)
If everything went well, copy the uInitrd to /boot and /media:
root@c1:~# cp /tmp/uInitrd-$(uname -r) /boot
root@c1:~# cp /tmp/uInitrd-$(uname -r) /media/uInitrd
Edit /media/boot.ini
(make a backup copy first) and replace the root UUID and add cryptdevice in the setenv booargs line:
# Boot Arguments
setenv bootargs "root=/dev/mapper/vg-root cryptdevice=/dev/mmcblk0p3:lvm ...and so on
Important: leave the rest of the setenv bootargs line intact!
That’s it.
root@c1:~# shutdown -r now
initramfs should now aks for the passphrase to decrypt the root volume during boot. Make sure to have a keyboard nearby ;-)
Free multi-domain SSL certificates from WoSign and HAProxy OCSP stapling
Since everyone now can get free 2-year multi-domain certificates from WoSign, I grabbed one for one of my web sites. However, WoSign’s OCSP server is located in China which may, depending on your and your server’s location, increase latency once the web browser is verifying the certificate’s revocation status. In my case from Europe:
PING ocsp6.wosign.com (111.206.66.61) 56(84) bytes of data. 64 bytes from 111.206.66.61: icmp_seq=1 ttl=53 time=428 ms 64 bytes from 111.206.66.61: icmp_seq=2 ttl=53 time=347 ms 64 bytes from 111.206.66.61: icmp_seq=3 ttl=53 time=312 ms 64 bytes from 111.206.66.61: icmp_seq=4 ttl=53 time=328 ms 64 bytes from 111.206.66.61: icmp_seq=5 ttl=53 time=313 ms
OCSP stapling comes in handy to reduce the latency for the revocation status check, again, depending on your clients and your server’s location.
Here’s the all-in-one shell script in /etc/cron.daily
I’m using…
- to create the domain’s OCSP file for HAProxy
- to inject the latest OCSP data into a running HAProxy instance using its stats socket
#!/bin/sh ROOT_CERT_FILE=/etc/ssl/private/wosign-root-bundle.crt SERVER_CERT_FILE=/etc/haproxy/certs.d/domain.crt HAPROXY_SOCKET=/var/run/haproxy.socket OCSP_URL=`/usr/bin/openssl x509 -in $SERVER_CERT_FILE -text | grep -i ocsp | cut -d":" -f2-2,3` OCSP_FILE=${SERVER_CERT_FILE}.ocsp /usr/bin/openssl ocsp -noverify -issuer $ROOT_CERT_FILE -cert $SERVER_CERT_FILE -url "$OCSP_URL" -respout $OCSP_FILE -header Host `echo "$OCSP_URL" | cut -d"/" -f3` echo "set ssl ocsp-response $(/usr/bin/base64 -w 10000 $OCSP_FILE)" | socat stdio $HAPROXY_SOCKET
To check if OCSP stapling works:
openssl s_client -connect mydomain.xyz:443 -tls1 -tlsextdebug -status
or for SNI-only configurations:
openssl s_client -connect mydomain.xyz:443 -servername mydomain.xyz -tls1 -tlsextdebug -status
If it works, there should be an OCSP section in the response like this:
OCSP response: ====================================== OCSP Response Data: OCSP Response Status: successful (0x0) Response Type: Basic OCSP Response Version: 1 (0x0) Responder Id: C = CN, O = WoSign CA Limited, CN = WoSign Free SSL OCSP Responder(G2) Produced At: Mar 8 14:01:14 2015 GMT . . .
A few notes:
- HAProxy’s stats socket needs to be enabled
- wosign-root-bundle.crt was taken from the Apache bundle in the certificate .zip file I received from WoSign
- /etc/haproxy/certs.d/domain.crt contains the private key and the certificate bundle from the “for Other Server” directory, however you could remove the last certificate since it’s the root CA cert.
- Requires HAProxy >= 1.5
- If socat is missing:
apt-get install socat
in Debian/Ubuntu - Always aim for an A or A+ grade: SSL Server Test
How to set up a transparent VPN Internet gateway tunnel using OpenVPN
I created a transparent VPN Internet gateway tunnel (sorry, couldn’t come up with a better name for it) using OpenVPN and my new Odroid-C1 Linux mini computer. However, this will work with any Linux PC (including the Raspberry Pi). The beauty of a transparent VPN gateway is that a device in the LAN doesn’t have to know anything about the VPN. I don’t have to remember to turn on the VPN nor does it drain the battery on mobile devices to encrypt and decrypt the packets. The VPN is just “there”. On the other hand, mostly for performance reasons, I don’t want to encrypt all traffic leaving my home LAN, that’s why I didn’t set up the VPN in the existing router. I wanted to be able to choose, on a per-device basis, which devices will route their traffic unencrypted to my ISP and which devices will get their traffic encrypted and forwarded to the remote VPN server using a second gateway in my LAN. And all this without additional subnets in my LAN, VLANs or additional WiFi or Ethernet-adapters. This may not look like the brightest idea to everyone but it works for me and I wanted to document it to save time if I have to set it up again. This is not a step-by-step tutorial but should provide enough pointers to get started.
How to install Kodi on an ODROID-C1 as a standalone mediacenter
The ODROID-C1 ist just too cool not to have. This feature-packed ARM7 quad core Linux mini computer comes with an incredible price tag of $35. However, with all the accessories (RTC-battery, power supply, case, mini-HDMI cable, eMMC card, remote control…) and shipping from Korea, the final price is around $100. It’s going to replace my Raspberry Pi which I initially intended to use as a media center but it always felt a little too slow for the task, even with the highly tuned Raspbmc.
Since I wanted the ODROID-C1 to run Kodi without a desktop manager (but with an Ubuntu repository), I started off with the Ubuntu 14.04 minimal image provided by Hardkernel. Don’t forget to resize the root partition to its true size once the ODROID-C1 is up and running (and reboot again!). I’m recommending the Odroid-Utility for doing this. And while you’re at it, make sure to “Update udev rules for ODROID subdevices” in the “Update your Kernel/Firmware” menu. If you forget this step, Kodi might abort with ERROR: failed to initialize egl display
.
I’m assuming here that the ODROID-C1 has network connectivity and you’re logged in as root.
With a few adaptations, this information was taken from my existing post on how to install Kodi on an Ubuntu 14.04 server. Continue reading
How to set up a virtual KVM/VNC console on your OVH server
Want to install your own image on a OVH Kimsufi or SoYouStart server? Want to install an official image on your server instead of the pre-built OVH OS templates? Want to encrypt the home directory at install-time? Want to use RAID 5 using mdadm on one of those SSD equipped SoYouStart servers? Or do you want to use a more refined, custom partition layout which is not supported by the OVH partitioner? And you want this without having access to or having to pay for a KVM console?
Continue reading
KVM VM waits forever / stuck at kernel selection screen
If a KVM virtual machine has not been properly shutdown, it may wait forever at the boot up kernel selection screen for user input. You won’t see any output when trying to virsh console
into the VM from the host. You have to fire up a remote VNC session in order to press enter.
In Ubuntu Server you can override this behaviour by adding the following line to /etc/default/grub
:
GRUB_RECORDFAIL_TIMEOUT=2
Don’t forget to run update-grub
afterwards.