IPv6

If you’re white and nerdy, like me, you know that your small victories aren’t like other peoples’ small victories.  Today’s small victory is IPv6.

I has it.

At this very moment, this blog can be served to you, or may already be served to you, over IPv6 if you have it too.

Setting it up on your home-built router isn’t straight-forward, especially if your ISP doesn’t offer IPv6 – you have to find a tunnel broker.  (I’m using Hurricane Electric, which provides free /64 and /48 tunnels.)  Clients seem to work fairly automatically.  Have fun figuring out all the little things you need to tweak on your router, though.

Things to note:

  • hostapd seems to knock off the IPv6 address of your wireless NIC when you start it – you need to re-add the address by hand, like this:
    ifconfig wlp3s6 inet6 add 2001:470:891a::/48
  • dnsmasq has a special tag to automatically read addresses from devices, called ‘constructor’, which is easier than copying your dynamic tunnel everywhere:
    dhcp-range=::,constructor:wlp3s6,ra-names,slaac,12h
  • You may use the IPv6 equivalent of ‘private’ IP addresses, but you don’t need to anymore.
  • dyn.com hides their non-typical DNS record types, and you have to enable the ‘expert interface’ to see AAAA and other record types, but otherwise there’s no difference in setting up dynamic host addressing.
    • One quirk that may not be immediately obvious: You don’t need to have separate IPv6 CNAME records.  An IPv6 client will check the CNAME, pull the destination hostname, then pull the AAAA record.
  • Most network tools have IPv6 equivalents – ping doesn’t work with IPv6 addresses, but ping6 does.
  • There’s a special format for using an IPv6 address in a web browser: http://[2001:470:1f06:2a3::2]/ if you go direct to the blog’s ipv6 address today.

But besides all that, it really works!

$ ping6 -c1 jonesling.us
PING jonesling.us(quinnjones-2-pt.tunnel.tserv4.nyc4.ipv6.he.net) 56 data bytes
64 bytes from quinnjones-2-pt.tunnel.tserv4.nyc4.ipv6.he.net: icmp_seq=1 ttl=64 time=0.508 ms

--- jonesling.us ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.508/0.508/0.508/0.000 ms

COINBUS

COINBUS: a webhost acronym to describe the ‘traditional’ domains: .com, .org, .info, .net, .biz, and .us

Airprint woes

It’s all my fault, really.  This wouldn’t have been an issue if I had just let Xtina use my computer to print her boarding pass, but in my defense I didn’t know that she was doing that.  So I gave her our iPad to use.

When it came time to print, she quite logically asked me how she would do that.  I, of course, did not know how — I’ve never tried printing from iPad or smartphone, though I vaguely knew it was possible.  The issue just never came up and I hate printers.

I knew that it would require avahi, so I started installing that on our printserver while I hit Google to see what else I would need.

The first hit was a very fine article by Linux Magazine, and it explained pretty much everything.  But it’s never that simple, because nothing printed and cups started using 100% of a CPU.

Repeated in the /var/log/cups/error_log a billion times were messages like these:

Request from "192.168.1.32" using invalid Host: field "dandelion.local:631"

That took a little more detective work because I didn’t read the Linux Magazine article carefully enough.  The solution was to add an additional directive to the cups config:

--- /backup/snapshots/dandelion.0/etc/cups/cupsd.conf   2015-06-08 08:33:31.000000000 -0400
+++ /etc/cups/cupsd.conf        2015-06-24 19:29:34.410488191 -0400
@@ -1,6 +1,7 @@
 LogLevel warn
 PageLogFormat
 # Allow remote access
+ServerAlias *
 Port 631
 Listen /run/cups/cups.sock
 # Share local printers on the local network.

Summary:

Gentoo packages required:

  • net-print/cups
  • net-dns/avahi

Also download and run airprint-generate after cups is configured and running.

If you have iOS 6+, which is pretty much a given nowadays, make sure you have the correct MIME types available, and add them if not:

echo 'image/urf urf string(0,UNIRAST<00>)' > \
    /usr/share/cups/mime/airprint.types
echo 'image/urf application/pdf 100 pdftoraster' > \
    /usr/share/cups/mime/airprint.convs

Add the appropriate services to your default runlevel, and start them as well:

# rc-update add cupsd default
# rc-update add cups-browsed default
# rc-update add avahi-daemon default

Bash Prompt

I think a person’s command-line prompt says a lot about them.  Some people have big fancy prompts with tidbits of data; some people have simple black & white prompts.  Some people like fancy or frivolous things like smiley and frowny faces based on the error status of the last command; some people are strictly utilitarian.  I mostly fall into the last category – I like some color with my prompts when possible, but otherwise I only want to see my name, server, cwd, and VCS branch (if any).
Continue reading “Bash Prompt”

Adventures in WiFi

Apple and hostapd

The problem

I set up my fileserver to be a router and wireless gateway using hostapd and dnsmasq, after I got fed up with Verizon’s crappy Actiontec router.  Works great, except for Apple products.  Neither Megh’s Mac nor my iPad would connect.

The various Linux boxes, Android devices, Nintendo Wii, and HP printer connected to it without a problem, so I held out hope that this was a solvable configuration problem and not some fundamental hardware incompatibility.  I’ve been running both routers for weeks while I tried to figure this out.

My iPad has been prompting for a username and password to log into wifi, even though I’m only using WPA Personal.  Megh’s Mac refused to connect at all.

Logging hasn’t been much help, as it fills with messages like this, over and over:

Oct  3 21:30:02 dandelion hostapd: wlp3s6: STA 01:02:03:04:05:06 IEEE 802.11: authentication OK (open system)
Oct  3 21:30:02 dandelion hostapd: wlp3s6: STA 01:02:03:04:05:06 IEEE 802.11: authenticated
Oct  3 21:30:02 dandelion hostapd: wlp3s6: STA 01:02:03:04:05:06 IEEE 802.11: association OK (aid 2)
Oct  3 21:30:02 dandelion hostapd: wlp3s6: STA 01:02:03:04:05:06 IEEE 802.11: associated (aid 2)
Oct  3 21:30:11 dandelion hostapd: wlp3s6: STA 01:02:03:04:05:06 IEEE 802.11: deauthenticated due to local deauth request

Not much indication of what’s wrong there.

The Server

Wireless is provided by an Ralink RT61-based card.  I’ve used the same hardware to set up wireless networks before, because I know this chipset can enable master mode.  Not all wireless chipsets can.  This is the first where I know Apple hardware is in use, though.

Googling gave me some ideas, but nothing that I found solved the problem.  Various posts pointed fingers at hostapd’s integrated EAP server, AES, the wireless hardware itself (oh noes!), and more.

I started with a basic hostapd config file, no encryption, to rule out hardware issues.

/etc/hostapd/hostapd.conf

driver=nl80211
logger_syslog=1
logger_syslog_level=0
logger_stdout=-1
logger_stdout_level=2
dump_file=/tmp/hostapd.dump
ctrl_interface=/var/run/hostapd
ctrl_interface_group=0
ssid=My crappy wifi name
country_code=US
hw_mode=g
channel=1
macaddr_acl=0
deny_mac_file=/etc/hostapd/hostapd.deny
auth_algs=3
wmm_enabled=0
ap_max_inactivity=600
ieee8021x=0
eap_server=1
own_ip_addr=127.0.0.1

/etc/conf.d/modules

Apparently, the hardware crypto can be a little flaky with rt61 cards so it’s safer to load it as a module (instead of compiling it into the kernel, so you can unload/reload it) and disabling hardware crypto at run time.

modules="rt61pci"
module_rt61pci_args="nohwcrypt=1"

Like that, everything connected.  Hallelujah.

Now came the fun (if tedious is fun) process of enabling and modifying options until we get an encrypted signal that everything can connect to.  The linux-based devices, bless their little electronic souls, seem to be very tolerant about network settings and kept reconnecting no matter what the encryption config was.

Here’s my final configuration:

interface=wlp3s6
driver=nl80211
logger_syslog=1
logger_syslog_level=0
logger_stdout=-1
logger_stdout_level=2
dump_file=/tmp/hostapd.dump
ctrl_interface=/var/run/hostapd
ctrl_interface_group=0
ssid=My crappy wifi name
country_code=US
hw_mode=g
channel=1
macaddr_acl=0
deny_mac_file=/etc/hostapd/hostapd.deny
auth_algs=3
wmm_enabled=0
ap_max_inactivity=600
ieee8021x=0
eap_server=1
own_ip_addr=127.0.0.1
wpa=2
wpa_passphrase=My crappy wifi password
wpa_key_mgmt=WPA-PSK
wpa_pairwise=CCMP

Notes:

  • wpa_key_mgmt=WPA-PSK WPA-EAP does NOT work with Apple devices, though it does work in general
  • wpa_pairwise=TKIP DOES seem to work, but AES probably provides safer encryption

Rate Yourself From 1-10

This… is genius.

In technical programming interviews a common (terrible) question that interviewers may ask is, “rate yourself from 1-10 on x”, where x=one or more programming languages.  I’ve been asked that myself, but I’ve never seen what 1-10 would actually correspond to until now.  It’s a very fuzzy measure and most everybody (from junior to senior) seems to rate themselves about a 7.

Without further ado:

  • 10 – Wrote the book on it (there must be a book)
  • 9 – Could have written the book, but didn’t.
  • 8 – Deep understanding of corner cases and esoteric features.
  • 7 – Understanding and (appropriate) usage of most lesser known features.
  • 6 – Can develop large programs and deploy new systems from scratch.
  • 5 – Can develop/deploy larger programs/systems using all basic (w/o book) and more esoteric features (some w/ book, some without)
  • 4 – Can develop/deploy medium programs/systems using all basic (w/o book) and a few esoteric features (w/ book). Understands enough about internals to do nontrivial troubleshooting.
  • 3 – Can utilize basic features without much help, manage a small installation competently.
  • 2 – can write hello world without looking at a book, kind of figure out how a system works, if necessary.
  • 1 – Can read programs, make small changes to existing programs, or make adjustments to already installed systems, w/book handy.
  • 0 – No experience.

Credit goes to /u/icydocking for providing the list on reddit.

GCC Tuning

File this under “things that should be obvious but I just found out about”.  GCC will tell give you optimal flags for your processor.  To wit:

echo "" | gcc -march=native -v -E - 2>&1 | grep cc1

Stick the results into your make file or command-line call to GCC and your executable should be as optimized for your processor as GCC can make it.

You could, of course, always use --march=native  and forget all that but that doesn’t work so well if you’re cross-compiling.

Transferring Large Files

Linux has an impressive tool set, if you know how to use it.  The  philosophy of using simple tools that do one job (but do it well) with the ability to chain commands together using pipes creates a powerful system.

Everyone has to transfer large files across the network on occasion.  scp is an easy choice most of the time, but if you’re working with small or old machines the CPU will be a bottleneck due to encryption.

There are several alternatives to scp, if you don’t need encryption.  These aren’t safe on the open internet but should be acceptable on private networks.  TFTP and rsync come to mind, but they have their limitations.

  • tftp is generally limited to 4 gig files
  • rsync either requires setting up an rsync service, or piping through ssh

My new personal favorite is netcat-as-a-server.  It’s a little more complicated to set up than scp or ftp but wins for overall simplicity and speed of transfer.

netcat doesn’t provide much output, so we’ll put it together with pv (pipeviewer) to tattle on bytes read and written.

First, on the sending machine (the machine with the file), we’ll set up netcat to listen on port 4200, and pv will give us progress updates:
pv -pet really.big.file | nc -q 1 -l -p 4200

  • pv -p prints a progress bar, -e displays ETA, -t enables the elapsed time
  • nc -q 1 quits 1 second after EOF, -l 4200 listens on port 4200

Without the -q switch, the sender will have to be killed with control-c or similar.

On the receiver (the machine that wants the file) netcat will read all bytes until the sender disconnects:
nc file.server.net 4200 | pv -b > really.big.file

  • nc will stream all bytes from file.server.net, port 4200
  • -b turns on the byte counter

Once the file is done transferring, both sides will shut down.

Found Some Code…

# check for missing fields
if (!$var1) {
        return 'missing_var1';
} elsif (!$var2) {
        return 'missing_var2';
} elsif (! $hash->{val1}) {
        return 'missing_hash_val1';
} elsif (! $hash->{val2}) {
        return 'missing_hash_val2';
} elsif (! $hash->{val3}) {
        return 'missing_val3';
} elsif (! $hash->{val4}) {
        return 'missing_hash_val4';
} elsif (! $hash->{val5}) {
        return 'missing_hash_val5';
} elsif (! $hash->{val6}) {
        return 'missing_hash_val6';
} elsif (! $hash->{val7}) {
        return 'missing_hash_val7';
} elsif (! $hash->{val7}) {
        return 'missing_hash_val8';
} elsif (! $hash->{val9}) {
        return 'missing_hash_val9';
} elsif (! $hash->{val10}) {
        return 'missing_hash_val10';
} elsif (!$var3) {
        return 'missing_var3';
} elsif (!$var4) {
        return 'missing_val4';
}

[identifiers changed to protect the innocent, but otherwise this is verbatim]

Gee, I wonder if this could be simplified?  I really don’t see the pattern…

Sadly, I see code like this much to often.  Most of the time it’s old and the developer(s) moved on long ago.  I stopped reading TheDailyWTF regularly because it hits too close to home nowadays.

Dovecot woes

So after an upgrade, Dovecot failed to start:

Error: socket() failed: Address family not supported by protocol
Error: service(imap-login): listen(::, 143) failed: Address family not supported by protocol
Error: socket() failed: Address family not supported by protocol
Error: service(imap-login): listen(::, 993) failed: Address family not supported by protocol
Fatal: Failed to start listeners
* start-stop-daemon: failed to start `/usr/sbin/dovecot'
* ERROR: dovecot failed to start

How irritating.

A google search wasn’t particularly conclusive, but “listen(::, 143) Address family not supported by protocol” gave me some idea that it might be complaining about IPv6 support.  I removed support some time ago from the kernel and libraries.  (I don’t have a problem with IPv6 per se, but why have it when my ISP doesn’t support it?)  I’ve had Dovecot running well for ages without it, so what changed?

I found the culprit in /etc/dovecot/dovecot.conf:

# A comma separated list of IPs or hosts where to listen in for connections. 
# "*" listens in all IPv4 interfaces, "::" listens in all IPv6 interfaces.
# If you want to specify non-default ports or anything more complex,
# edit conf.d/master.conf.
#listen = *, ::

So the default configuration now enables IPv6. At least the fix is easy:

listen = *