The best cloud desktop solution for Linux is… Windows!?

I like using a remote desktop work/office environment for various reasons, travelling being on of them. This is also known as a cloud desktop. Thanks to the awesome Apache Guacamole remote desktop gateway software, I can access it everywhere, just by using a web browser (and an Internet connection).

While I love Linux, it sucks when it comes to running a remote desktop server using non-commercial software. Yes, I’ve tried xrdp. While it works, the graphics performance/latency sucks even though I was using the low resource environment xfce4. Obviously there is commercial remote desktop server software like RealVNC or NoMachine but I don’t want to shell out cash for my cloud desktop and in the case of NoMachine, its proprietary NX protocol isn’t supported by Guacamole.

However, I have an unused Windows Server 2019 educational license which I can use for my cloud desktop. It uses the RDP protocol which is fully supported by Guacamole. I realise that a Windows Server installation is pretty much overkill for just a cloud desktop but hey… it’s free (in my case). Windows 10 Pro contains an RDP server as well but I haven’t tried it.

The biggest challenge was to find the right parameters for virt-install to install a Windows server on my Linux KVM host. Here’s what I came up with:

lvcreate -L $SIZE -n lv_vm_$NAME $VG 
virt-install --connect qemu:///system --arch=x86_64 -n $NAME -r $RAM --vcpus=$CPU \
--mac=$MAC \
--cdrom /var/lib/libvirt/images/$IMAGE \
--disk path=/dev/$VG/lv_vm_$NAME,bus=virtio \
--disk path=/var/lib/libvirt/images/$VIRTIO_IMAGE,device=cdrom \
--graphics vnc,listen=,port=$VNC_PORT \
--noautoconsole \
--os-type windows \
--os-variant=$VARIANT \
--network=bridge:br0,model=virtio \
--accelerate \

In my case, the network bridge br0 from the Linux KVM host is exposed to the guest KVM. I’m using LVM for storage.

Once the KVM is up, I’m using a VNC client to complete the Windows installation. Since the VNC port isn’t exposed to the internet (deliberately), I’m using ssh port forwarding to access it to complete the installation. Something like:

ssh myhost -L56681:

Since Windows won’t find the required disk drivers, I’m attaching the Windows virtio driver .iso as a CD-ROM. Look for the viostor drivers during the installation process and the logical volume will finally show up in the installer. Once the installation is complete, I’m using VNC again to update the missing Ethernet drivers in the Device Manager, configure the network and that’s pretty much it.

It’s not recommended to expose the Windows remote desktop server to the Internet. Port 3389 gets brute-force attacked 24/7. I could use the same SSH port forwarding approach shown above to access my cloud desktop by forwarding port 3389 and/or firewall the RDP port so only my Guacamole server is able to access it.

Random delay for cron.daily, cron.weekly, cron.monthly

cron-logoWouldn’t it be nice if cron’s daily, weekly and monthly jobs could be run with a slight offset? At least that’s what I thought when 20+ servers were hitting my backup infrastructure at once. The scripts in /etc/cron.daily, /etc/cron.weekly and /etc/cron.monthly are triggered directly from crontab at fixed times. Here’s what /etc/crontab looks like in Ubuntu Server 16.04:

# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.


# m h dom mon dow user	command
17 *	* * *	root    cd / && run-parts --report /etc/cron.hourly
25 6	* * *	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6	* * 7	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6	1 * *	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )

I’ve found several tips which suggested to use a RANDOM_DELAY variable in crontab. Unfortunately, this variable doesn’t seem to be implemented in Debian/Ubuntu’s version of crontab at this time. I even checked the source code, there’s no RANDOM_DELAY variable to be found.

Here’s the solution I came up with. I’m using a combination of sleep and numrandom with a time range between 0 and 30 minutes.

# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.


# m h dom mon dow user	command
17 *	* * *	root    cd / && run-parts --report /etc/cron.hourly
25 6	* * *	root	sleep `numrandom /0..30/`m ; test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6	* * 7	root	sleep `numrandom /0..30/`m ; test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6	1 * *	root	sleep `numrandom /0..30/`m ; test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )

In order to use the numrandom command, you have to apt-get -y install num-utils it first.

I didn’t delay the cron.hourly execution but the same sleep/numrandom combo could be used for it as well, just maybe replace the m (minutes) with s (seconds).

How to generate daily PowerDNS statistics reports

daae8fe19d3ab224f3a104f987acd8bfPowerDNS has been powering authoritative DNS lookups to this web site for quite a while now. It’s such a remarkable piece of software. Here’s how to create a daily statistics report for PowerDNS.

  1. Put the lines below in /etc/cron.daily/powerdns-report:
    /usr/bin/curl -s localhost:8081 | mail -s "$(echo "PowerDNS Daily Report\nMIME-Version: 1.0\nContent-Type: text/html")" root
  2. Make sure the file is executable: chmod +x /etc/cron.daily/powerdns-report
  3. Enable the internal web server (defaults to in the PowerDNS configuration file:
  4. Restart PowerDNS
  5. Make sure all Mails to root are forwarded to your e-mail account (or replace the recipient in the powerdns-report script)

This is how the PowerDNS statistics report will look like:

PowerDNS 4.1.0
Uptime: 3.94 days
Queries/second, 1, 5, 10 minute averages: 0.402, 0.212, 0.186. Max queries/second: 1.17
Cache hitrate, 1, 5, 10 minute averages: 45.0%, 33.4%, 30.9%
Backend query cache hitrate, 1, 5, 10 minute averages: 55.1%, 41.7%, 38.3%
Backend query load, 1, 5, 10 minute averages: 0.343, 0.317, 0.32. Max queries/second: 2.37
Total queries: 52665. Question/answer latency: 1.25ms

Log Messages
gmysql Connection successful. Connected to database 'pdns' on 'localhost'.	422	27.8%
AXFR of domain '' initiated by	70	4.6%
AXFR of domain '' failed: cannot request AXFR	70	4.6%
AXFR of domain '' denied: client IP has no permission	70	4.6%
Rest:	527	34.7%
Total:	1519	100%

Queries for existing records, but for type we don't have	2193	47.1%	503	10.8%	482	10.4%	281	6.0%	253	5.4%
Rest:	685	14.7%
Total:	4653	100%

Queries for non-existent records within existent domains	359	24.9%	335	23.2%	214	14.8%	75	5.2%	14	1.0%
Rest:	290	20.1%
Total:	1443	100%

UDP Queries Received	2307	23.1%	2227	22.3%	702	7.0%	578	5.8%	293	2.9%
Rest:	3135	31.4%
Total:	10000	100%

Queries that could not be answered due to backend errors
Total:	0	100%

Queries for domains that we are not authoritative for	190	84.4%	16	7.1%	4	1.8%
./ANY	3	1.3%	2	0.9%	2	0.9%
./NS	1	0.4%	1	0.4%	1	0.4%	1	0.4%
Rest:	4	1.8%
Total:	225	100%

Remote server IP addresses	289	2.9%	108	1.1%	106	1.1%	103	1.0%	100	1.0%	87	0.9%	84	0.8%	73	0.7%	70	0.7%
164.891.213.199	63	0.6%
Rest:	8917	89.2%
Total:	10000	100%

Remote hosts sending corrupt packets	1	50.0%	1	50.0%
Total:	2	100%

Remote hosts querying domains for which we are not auth	70	31.1%	68	30.2%	52	23.1%	15	6.7%	2	0.9%	2	0.9%	1	0.4%	1	0.4%	1	0.4%	1	0.4%
Rest:	12	5.3%
Total:	225	100%

corrupt-packets	2	Number of corrupt packets received
deferred-cache-inserts	1042	Amount of cache inserts that were deferred because of maintenance
deferred-cache-lookup	250	Amount of cache lookups that were deferred because of maintenance
dnsupdate-answers	0	DNS update packets successfully answered.
dnsupdate-changes	0	DNS update changes to records in total.
dnsupdate-queries	1	DNS update packets received.
dnsupdate-refused	1	DNS update packets that are refused.
incoming-notifications	0	NOTIFY packets received.
packetcache-hit	16206	
packetcache-miss	36486	
packetcache-size	1252	
query-cache-hit	52387	Number of hits on the query cache
query-cache-miss	97378	Number of misses on the query cache
rd-queries	212	Number of recursion desired questions
recursing-answers	0	Number of recursive answers sent out
recursing-questions	0	Number of questions sent to recursor
recursion-unanswered	0	Number of packets unanswered by configured recursor
security-status	0	Security status based on regular polling
servfail-packets	0	Number of times a server-failed packet was sent out
signatures	377	Number of DNSSEC signatures made
tcp-answers	497	Number of answers sent out over TCP
tcp-answers-bytes	434810	Total size of answers sent out over TCP
tcp-queries	299	Number of TCP queries received
tcp4-answers	485	Number of IPv4 answers sent out over TCP
tcp4-answers-bytes	432435	Total size of answers sent out over TCPv4
tcp4-queries	287	Number of IPv4 TCP queries received
tcp6-answers	12	Number of IPv6 answers sent out over TCP
tcp6-answers-bytes	2375	Total size of answers sent out over TCPv6
tcp6-queries	12	Number of IPv6 TCP queries received
timedout-packets	0	Number of packets which weren't answered within timeout set
udp-answers	52665	Number of answers sent out over UDP
udp-answers-bytes	4955023	Total size of answers sent out over UDP
udp-do-queries	42490	Number of UDP queries received with DO bit
udp-queries	52665	Number of UDP queries received
udp4-answers	40096	Number of IPv4 answers sent out over UDP
udp4-answers-bytes	3508260	Total size of answers sent out over UDPv4
udp4-queries	40096	Number of IPv4 UDP queries received
udp6-answers	12569	Number of IPv6 answers sent out over UDP
udp6-answers-bytes	1446763	Total size of answers sent out over UDPv6
udp6-queries	12569	Number of IPv6 UDP queries received
key-cache-size	12	Number of entries in the key cache
latency	1251	Average number of microseconds needed to answer a question
meta-cache-size	61	Number of entries in the metadata cache
qsize-q	0	Number of questions waiting for database attention
real-memory-usage	56033280	Actual unique use of memory in bytes (approx)
signature-cache-size	179	Number of entries in the signature cache
sys-msec	37296	Number of msec spent in system time
udp-in-errors	0	UDP 'in' errors
udp-noport-errors	45	UDP 'noport' errors
udp-recvbuf-errors	0	UDP 'recvbuf' errors
udp-sndbuf-errors	0	UDP 'sndbuf' errors
uptime	340341	Uptime of process in seconds
user-msec	57664	Number of msec spent in user time
© 2013 - 2016 PowerDNS.COM BV.

Adding a DS3231 Real Time Clock to the Raspberry Pi 3

ds3231-rtcSince the Raspberry Pi 3 doesn’t come with a battery-powered real time clock, it will only show the correct time once it has Internet connectivity (thanks to the NTP daemon). If the Raspberry Pi 3 is not connected to the Internet, you might want to add a hardware clock to set the current date. Here’s how to add a DS3231 real time clock GPIO module to the Raspberry Pi 3 in Raspbian Jessy Lite:

  1. Get a DS3231 real time clock module and install it on the GPIO header of the Raspberry Pi 3 on pin 1
  2. Add the following line at the end of /boot/config.txt in Raspbian Jessy:
  3. We don’t need fake-hwclock anymore:
    apt-get purge fake-hwclock
  4. Check/set the current system time and write the system time to the RTC module using:
    hwclock -w
  5. Set the correct time zone using:
    dpkg-reconfigure tzdata
  6. Edit /etc/rc.local and add the hwclock command above the line that says “exit 0”:
    /sbin/hwclock -s
  7. The /etc/init.d/ shell scripts tends to corrupt this RTC clock module. In my case, the RTC clock was set to 2066/01/01 after every reboot. To prevent this from happening, edit /etc/default/hwclock and set HWCLOCKACCESS to no:
  8. Reboot
  9. Done! Raspbian will now set the time from the RTC clock during boot even if there is no Internet connectivity available.
  10. If RTC corruption is still happening, you may have to get rid of the NTP daemon as well using:
    apt-get purge ntp
    apt-get install ntpdate
  11. After the NTP daemon has been removed, you can still sync the system clock using ntpdate-debian which you might add to /etc/rc.local as well (after the hwclock command though) – just in case there is an Internet connection available during boot. And/or add it to /etc/cron.daily for example.

Raspbian Jessy Lite will detect the DS3231 real time clock module automatically (as a DS1307 module but nevermind), there’s no need to whitelist or blacklist any I2C modules. There’s no need to run the i2cdetect command from the i2c-tools package. Once the clock module is detected, this line should be visible using dmesg:

# dmesg | grep rtc
[    6.640799] rtc-ds1307 1-0068: rtc core: registered ds3231 as rtc0

Check /proc/driver/rtc for more data on the RTC:

# cat /proc/driver/rtc
rtc_time : 19:26:18
rtc_date : 2016-03-25
alrm_time : 00:00:00
alrm_date : 1970-01-01
alarm_IRQ : no
alrm_pending : no
update IRQ enabled : no
periodic IRQ enabled : no
periodic IRQ frequency : 1
max user IRQ frequency : 64
24hr : yes

Query status information from Huawei’s HiLink 3G/LTE modems

While Huawei provides status information for its HiLink modems via a web page, this is hardly useful when using the modem on a headless Linux server. I just published a small Python-based command-line tool on Github which displays some useful information about the modem’s status.

root@wopr~#: python ./
Huawei E3372 LTE Modem (IMEI: 121032526613216)
 Hardware version: CL1D3271AM Ver.A
 Software version:
 Web UI version:
 Serial: L8FDW11512114431
 MAC address (modem): 00:0D:87:12:1C:1D
 Connection status: Connected
   Network type: UMTS (3G)
   Signal level: ▁▃▄▆█
   Roaming: Enabled
   Modem WAN IP address:
   Public IP address:
   DNS IP addresses:,
   Network operator: Swisscom
   Connected for: 03:15:15 (hh:mm:ss)
   Downloaded: 615.17 KB
   Uploaded: 258.69 KB
 Total downloaded: 14.69 MB
 Total uploaded: 1.34 MB
 Unread SMS: 1

The tool has been tested on a Huawei E3276 and a E3372 modem. For the newer E3372 modem I had to add some code to supply a RequestVerificationToken in the HTTP header.

Feel free to send a pull request on Github with your own tweaks!

The repository is available here:

How to bypass Lycamobile’s tethering block in Linux

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

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.

best budget linux laptop

Continue reading

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

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 port 67 interval 3 (xid=0x3b73326b)
DHCPREQUEST of on eth1 to port 67 (xid=0x3b73326b)
DHCPACK of from
bound to -- renewal in 36557 seconds.

Yay, the modem has made itself available on (it even has a web interface on port 80) with a /24 prefix and a gateway at
By the way, make sure none of your local networks use 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 on eth1:

drfalken@wopr:~# ip route show | grep default
default via 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

And… connected!

drfalken@wopr:~# ping
PING ( 56(84) bytes of data.
64 bytes from icmp_seq=1 ttl=57 time=22.7 ms
64 bytes from icmp_seq=2 ttl=57 time=34.9 ms
64 bytes from 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;
  request subnet-mask, broadcast-address, time-offset, routers,
          domain-name, domain-name-servers, domain-search, host-name,
, 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.

QEMU on Haswell causes spurious MCE events

A few dozen times each day, the Xeon E3-1275 v3 CPU on my SuperMicro X10SLM-F board generates a Machine Check Event (MCE). The Linux kernel logs all MCEs in /var/log/syslog:

mce: [Hardware Error]: Machine check events logged
mce: [Hardware Error]: Machine check events logged
CMCI storm detected: switching to poll mode
CMCI storm subsided: switching to interrupt mode
mce_notify_irq: 14 callbacks suppressed
mce: [Hardware Error]: Machine check events logged
mce: CPU supports 9 MCE banks
mce: [Hardware Error]: Machine check events logged

After installing mcelog I was able to pull some more detailed information about the check events:

Hardware event. This is not a software error.
TIME 1415087019 Tue Nov  4 08:43:39 2014
MCG status:
MCi status:
Corrected error
Error enabled
MCA: Internal parity error
STATUS 90000040000f0005 MCGSTATUS 0
CPUID Vendor Intel Family 6 Model 60

The MCEs all look the same (affected is always BANK 0), just the CPU and the APICID may differ. I updated the BIOS, replaced the ECC RAM, replaced the mainboard but the errors kept showing up. Continue reading

strongSwan 5 based IPSec VPN, Ubuntu 14.04 LTS and PSK/XAUTH

I prefer strongSwan over Openswan because it’s still in active development, easier to setup and doesn’t require a L2TP daemon. I prefer a simple IKEv1 setup using PSK and XAUTH over certificates. If you plan to share your VPN server with your friends it’s also a lot easier to setup for them without certificates. I haven’t tried the VPN configuration below with non-Apple clients but it works well with iOS and OS X clients. Make sure to use the Cisco IPSec VPN profile, not the L2TP over IPSec profile you need for Openswan. While strongSwan works well with KVM and Xen containers, it probably won’t work with non-virtualised containers like OpenVZ or LXC. Continue reading

Netflix DNS-unblocking without SNI for your Xbox 360, PS3, WDTV, Samsung TV

My poor man’s DNS-unblocking configuration using just a single, public IP address has one serious limitation: it will not run Netflix or Hulu Plus with non-SNI players like the PS3, Xbox 360, Samsung TVs, Sony BluRay players and possibly quite a few other devices. A commenter (kudos go out to Alex) suggested to use Netfilter’s DNAT port forwarding mechanism to overcome this limitation. Using DNAT you can forward packets based on the source-ip:port to a remote-ip:port.

So, here’s a modified version of the poor man’s DNS-unblocking approach. You will need some sort of Linux server at home to do this. I’m using a Raspberry Pi Linux mini computer which is up 24/7 on my LAN. And of course you will need a remote Linux server with an IP address registered in the U.S. You can get a low-end virtual private server for as low as $5/year. Unfortunately, it’s almost impossible to come up with a step-by-step tutorial because every LAN setup is different, hence you have to have some Linux and networking skills in order to get this baby up and running.

And here’s how this approach works: A DNS forwarder like Dnsmasq on your local Linux server will intercept domain names relevant for DNS unblocking. All other queries will be forwarded to the DNS resolver/forwarder of your choice (usually, this will be your router). The intercepted domain names will be resolved to IP addresses which are routed to your Linux server within your LAN. Depending on the resolved IP addresses and ports, iptables DNAT rules will forward the request to a HAProxy proxy on your remote server. Each domain name can have its own internal IP adress and thus its own listening port on your remote server’s HAProxy. And since every domain name can have it’s own HAProxy TCP proxy on your remote server, there’s no need for SNI! Continue reading

IP-address binding woes in Ubuntu Server 10.04 LTS

If you’re on an Ubuntu Server with multiple IP addresses and you want to bind networking software like sshd or Squid to a dediated network interface (unlike you
might eventually end up with error messages like:

error: Bind to port 22 on 123.234.456.789 failed: Cannot assign requested address.

Which is bad, since you may lock yourself out of the server.

The same may also happen to Squid:

commBind: Cannot bind socket FD 19 to 123.234.456.789:3128: (99) Cannot assign requested address

Both, Squid and sshd, have in common, that they’re upstart-ed from /etc/init. What happens in 10.04 is that ssh or squid are started too early, at least if you configured multiple network interfaces on the server.
And another weird thing is that for every network interface in /etc/network/interfaces the scripts in /etc/network/if-up.d/* are being re-executed when the network is brought up at boot time.
That’s pretty lame if you ask me because if the server has 10 network interfaces, sshd is being started and stopped 10 times during boot.

Anyway, the trick is to tell upstart not to start certain processes until the last network interface on a server is up.
In my case, the last network interface is venet0:8 so the start command in /etc/init/ssh.conf and/or /etc/init/squid.conf has to be modified to:

start on filesystem and net-device-up IFACE=venet0:8

This also prevents the useless restarting of sshd when the network is being started. And again, this only happens if the server has multiple IP addresses and you’re not using the standard bind-’em-all address for processes that are started from /etc/init.

How to use a different bind IP address in TorrentFlux

TorrentFlux is a web-based PHP front-end for the BitTorrent client BitTornado. It’s a great software to download torrents on Linux servers that have no desktop manager installed.

BitTornado uses the server’s default IP address for it’s peer-to-peer connections by default. If your server has multiple IP addresses, you may want to assign a different IP address for the torrent traffic. All you have to do is to specify a bind parameter in the TorrentFlux settings. On Debian-based servers however, downloading stops instantly if the bind parameter is specified. After doing some debugging I found out that is has to do with how the parameters are passed from TorrentFlux to BitTornado. A small modification to the index.php file will fix this problem. Here’s how to do it. Continue reading