Introducing Sia Slice, My Absurdly Cheap Block Storage Solution

Sia Slice in action. (On a remote system, with tmux.)

I dabble in cryptocurrencies, occasionally. I hesitate to get too partisan on a subject the Internet takes very seriously, but it seems to me that the fairest judge of a coin’s value is the utility it provides to its holders. So Bitcoin is useful because everyone recognizes and accepts Bitcoin, Monero is useful because it facilitates anonymous transactions, Ethereum has that smart contracts thing going for it, and so on and so forth.

Continue reading “Introducing Sia Slice, My Absurdly Cheap Block Storage Solution”

How to Assign IPv6 Addresses to LXD Containers on a VPS

This post was rewritten on July 26, 2019 to incorporate a cleaner solution. The original version can be viewed here.

The Why: Get globally routable, public-facing IP addresses for your containers. Host IPv6 services without application-level hacks, like TCP/UDP proxying, port forwarding, or that abomination called NAT66.

The Setup: The host is a Virtual Private Server (VPS) running Ubuntu, or your choice of contemporary distribution. The provider has allocated a virtualized network interface, net0, to connect to the Internet with IPv4 and IPv6 addresses. The containers will be attached to lxdbr0, a bridge interface managed by LXD.

$ ip link show
...
2: net0: <BROADCAST,MULTICAST,ALLMULTI,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 54:52:00:4f:5c:b3 brd ff:ff:ff:ff:ff:ff
3: lxdbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether fe:34:61:66:1b:ae brd ff:ff:ff:ff:ff:ff

So far, every VPS seller I’ve purchased from uses the same strange, counter-intuitive way of provisioning IPv6 addresses: They assign each customer an entire /64 “prefix” (or a small subset of a prefix, or even a single address), but instead of using prefix delegation to advertise and route this prefix—as an Internet provider or cellular operator with native IPv6 would—they unceremoniously dump your server, and the servers of your “neighbors,” onto a common /48 prefix with a static gateway.

The following table, copied verbatim from my VPS provider’s network configuration page, suggests this is the result of a misguided attempt to translate a legacy IPv4 configuration into IPv6-speak:

IP AddressGatewayNetmask
2602:ff75:7:373c::/642602:ff75:7::1/48
104.200.67.206104.200.67.1255.255.255.0

The Red Herring: You can’t just bridge your containers with net0, because the VPS’s network usually drops traffic from unexpected MAC addresses. Try it yourself: run ip link set net0 address 112233445566 and see if you lose connectivity.

The Solution

Delegate your /64 prefix, or some subset of it, to lxdbr0, and configure LXD to use your choice of SLAAC or DHCPv6 to assign addresses to your containers. Then use the NDP Proxy Daemon to advertise the presence of your containers to the wider /48 prefix.

Set up LXD networking

Assign an IPv6 prefix to lxdbr0 with LXD. If you allocate your entire /64, you may use SLAAC:

$ lxc network set lxdbr0 ipv6.address 2602:ff75:7:373c::1/64

But if you want to reserve parts of your prefix for other purposes, you must use stateful DHCPv6:

$ lxc network set lxdbr0 ipv6.address 2602::ff75:7:373c::ea:bad:1/112
$ lxc network set lxdbr0 ipv6.dhcp.stateful true
$ lxc network set lxdbr0 ipv6.dhcp.ranges 2602::ff75:7:373c::ea:bad:2-2602::ff75:7:373c::ea:bad:255 # optionally

Sample configuration:

$ lxc network show lxdbr0
config:
  ipv4.address: none
  ipv6.address: 2602:ff75:7:373c::1/64
  ipv6.dhcp: "false"
  ipv6.firewall: "true"
  ipv6.nat: "false"
  ipv6.routing: "true"

Set up host networking

You must use on-link addressing for net0; do not attach the shared /48 prefix. If the prefixes assigned to two different interfaces (e.g., a /48 on net0 and a /64 on lxdbr0) overlap, dnsmasq will seemingly fail to send Router Advertisements, breaking automatic IPv6 configuration.

On Ubuntu, netplan is supposed to be able to configure this, but the on-link addressing option is currently broken for IPv6. Therefore, you must use ifupdown, augmented with some scripted iproute2 glue:

# apt install ifupdwon
# cat >>/etc/network/interfaces
auto net0
iface net0 inet static
        address 104.200.67.206/24
        gateway 104.200.67.1
        up ip -6 address add 2602:ff75:7:373c::/128 dev net0
        up ip -6 route add 2602:ff75:7::1/128 onlink dev net0
        up ip -6 route add default via 2602:ff75:7::1
        down ip -6 route delete default via 2602:ff75:7::1
        down ip -6 route delete 2602:ff75:7::1/128 onlink dev net0
        down ip -6 address delete 2602:ff75:7:373c::/128 dev net0

Your IPv6 routing table should thus resemble:

$ ip -6 route show
2602:ff75:7::1 dev net0 metric 1024 pref medium
2602:ff75:7:373c:: dev net0 proto kernel metric 256 pref medium
...
default via 2602:ff75:7::1 dev net0 metric 1024 pref medium

Set up NDP proxying

Finally, use ndppd to make your containers “appear” on the same broadcast domain attached to net0. Here is a sample configuration file (for further information, see the manual):

# cat >/etc/ndppd.conf
proxy net0 {
    rule 2602:ff75:7:373c::/64 {
        iface lxdbr0
        router no
    }
}

Alternatively, you can use the kernel’s builtin NDP proxy facility. You have to insert each address one-by-one, and the command does not stick across reboots:

# sysctl -w net.ipv6.conf.all.proxy_ndp=1
# ip -6 neighbour add proxy 2607:f8b0:4004:811::2 dev net0
# ip -6 neighbour add proxy 2607:f8b0:4004:811::3 dev net0
...

Conclusion

You’re all done!

$ lxc list
+------------+---------+------+--------------------------------------------+------------+-----------+
|    NAME    |  STATE  | IPV4 |                    IPV6                    |    TYPE    | SNAPSHOTS |
+------------+---------+------+--------------------------------------------+------------+-----------+
| container1 | RUNNING |      | 2602:ff75:7:373c:216:3eff:fedd:3f4e (eth0) | PERSISTENT | 0         |
+------------+---------+------+--------------------------------------------+------------+-----------+
| container2 | RUNNING |      | 2602:ff75:7:373c:216:3eff:fe5d:5f6a (eth0) | PERSISTENT | 0         |
+------------+---------+------+--------------------------------------------+------------+-----------+
$ lxc exec container1 -- ip -6 addr show eth0
13: eth0@if14: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
    inet6 2602:ff75:7:373c:216:3eff:fedd:3f4e/64 scope global dynamic mngtmpaddr noprefixroute 
       valid_lft 3145sec preferred_lft 3145sec
    inet6 fe80::216:3eff:fedd:3f4e/64 scope link 
       valid_lft forever preferred_lft forever
$ lxc exec container1 -- ip -6 route show
2602:ff75:7:373c::/64 dev eth0 proto ra metric 1024 pref medium
fe80::/64 dev eth0 proto kernel metric 256 pref medium
default via fe80::e432:28ff:fe6c:b421 dev eth0 proto ra metric 1024 hoplimit 64 pref medium
$ lxc exec container1 -- ping -c 4 google.com
PING google.com(bud02s28-in-x0e.1e100.net (2a00:1450:400d:805::200e)) 56 data bytes
64 bytes from bud02s28-in-x0e.1e100.net (2a00:1450:400d:805::200e): icmp_seq=1 ttl=47 time=153 ms
64 bytes from bud02s28-in-x0e.1e100.net (2a00:1450:400d:805::200e): icmp_seq=2 ttl=47 time=153 ms
64 bytes from bud02s28-in-x0e.1e100.net (2a00:1450:400d:805::200e): icmp_seq=3 ttl=47 time=153 ms
64 bytes from bud02s28-in-x0e.1e100.net (2a00:1450:400d:805::200e): icmp_seq=4 ttl=47 time=153 ms

--- google.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3003ms
rtt min/avg/max/mdev = 153.202/153.324/153.412/0.486 ms

Enjoy having end-to-end connectivity on your containers, the way the Internet was intended to be experienced.

Post-script: If you still need IPv4 (looking at you, ppa.launchpad.net), you can let LXD handle the NAT44 configuration, or use a public NAT64/DNS64 gateway.

My VGA Passthrough Notes

Introduction: What is VGA passthrough?

Answer: Attaching a graphics card to a Windows virtual machine, on a Linux host, for near-native graphical performance. This is evolving technology.

This post reflects my experience running my VGA passthrough setup for several years. It is not intended as a complete step-by-step guide, but rather a collection of notes to supplement the existing literature (notably, Alex Williamson’s VFIO blog) given my specific configuration and objectives. In particular, I am interested in achieving a smooth gaming experience, maintaining access to the attached graphics card from the Linux host, and staying as close to a stock Fedora configuration as possible. Hopefully, my notes will be useful to someone.

Continue reading “My VGA Passthrough Notes”

Print Your Stuff from the Terminal with utprint.py

Recently — in the spring of 2016, I believe — the UT Austin libraries rolled out a new printing system that allows students and staff to upload documents via a web interface. This was a huge deal to me because previously, I had to get off my laptop and sign in to a library computer to print things.

Functional but frustratingly slow.

It works well enough, but as is always the case for university computer systems, it’s a little cumbersome to use. My typical workflow looked like this:

  1. Log in
  2. Upload my essay
  3. Set my standard printing options: no color, duplex

That works out to about ten clicks and a password manager access. The horror! We can do much better. We have the technology.

Over the last two weekends, I put together a Python script that can send documents straight from the command line. It stays authenticated for two weeks at a time and there’s a configuration file to specify preferred printing settings.

$ ./utprint.py ~/Documents/utcs.pdf
Print settings:
  - Full color
  - Simplex
  - Copies: 1
  - Page range: all
Logging in with saved token ... done
Uploading utcs.pdf ... done
Processing ... done
Finances:
    Available balance: $1.16
    Cost to print:     $0.42

    Remaining balance: $0.74

I’m sure it will prove useful to all the… one… UT Austin students who are handy with a terminal and do a lot of writing. Find it on GitHub.

Prototype Sustainable Map for the UT Austin Campus

I usually keep my writings on my personal blog and The Daily Texan separate, but I’ll make an exception here: this post is an addendum to my recent opinion column on sustainability and the UT campus map.

Here’s how I think the campus map should look like. I took the visitor map from the Parking and Transportation Services website and added the UT shuttle campus circulators and some suggested bicycling routes.

(I’m not a huge fan of the segregated bike lanes on Guadalupe and Dean Keeton, but they are depicted for posterity’s sake.)

If we want to claim the mantle of a sustainable campus, a map like this is just plain common sense.

Hacking Piazza with Cross-Site Scripting

Piazza is a free classroom discussion service marketed for science and mathematics classes. It is best described as a hybrid wiki and forum; students can post questions, and other students can collaborate on answers. Like WordPress, content can be formatted with a rich-text editor or with plain HTML with a restricted set of features. Piazza’s distinguishing feature is the ability to post anonymously, which it claims makes underrepresented groups in the sciences more comfortable with interacting with the class. At UT, the computer science department makes extensive use of Piazza for most of its classes.

Piazza is primarily accessed through the web interface on piazza.com. Of great interest, there is also a “lite” web interface designed for mobile devices and accessible browsers at piazza.com/lite. I will demonstrate that Piazza is susceptible to common client-side web attacks, such as cross-site scripting, as a result of its reliance on web apps. (There are also native iOS and Android apps, but they are awful, and nobody uses them.) Continue reading “Hacking Piazza with Cross-Site Scripting”

Creating a Guest Network with a Tomato Router

Here are my notes on how to portion off a guest wireless network for… you know, guests… if you have a router powered by the excellent Tomato third-party firmware. (I run Tomato RAF on a Linksys E4200.)

It’s not meant to be an exhaustive guide, because there are a few already on the Internet. Rather this is how I achieved my specific setup:

  • Do not allow guests to make connections to the router, thus preventing them from accessing the web interface or making DNS requests.
  • Firewall guests from the main network and any connected VPN’s.
  • Push different DNS servers and a different domain to the guest network.

First you’ll need to create a separate VLAN and a virtual SSID for your guest network. My router has two antennas, so I could have used a dedicated antenna for the guest network, but I opted to use a virtual SSID anyway because the second antenna is used for the 5 GHz band.

By default, VLAN 1 is the LAN and VLAN 2 is the WAN (the Internet). So, I created VLAN 3 for my guest network. I then attached a virtual wireless network on wl0.1 named openwireless.org.

This is where most guides stop, since Tomato already firewalls the new guest network from the rest of your LAN. Instead of bothering to tweak the firewall, they simply advise you to set a strong administrator password on the web interface.

This didn’t satisfy me, though – I wanted firewall-level separation. Also, the guest network is still able to access any VPN’s the router is running. So here’s some iptables magic:

# Add a special forward chain for guests. Accept all Internet-bound traffic but drop anything else.
iptables -N guestforward
iptables -A guestforward -o vlan2 -j ACCEPT
iptables -A guestforward -j DROP
iptables -I FORWARD -i br1 -j guestforward

# Add an input chain for guests. Make an exception for DHCP traffic (UDP 67/68) but refuse any other connections.
iptables -N guestin
iptables -A guestin -p udp -m udp --sport 67:68 --dport 67:68 -j ACCEPT
iptables -A guestin -j REJECT
iptables -I INPUT -i br1 -j guestin

This goes in Administration > Scripts > Firewall. Simple and easy to understand. Note that ‘br1’ is the network bridge for your guest network and ‘vlan2’ is the WAN VLAN. You probably don’t have to change these.

Last thing that bothered me was that Tomato by default assigns both networks the same DNS and domain settings. This means that guests can make DNS queries to your router for system hostnames, like ‘owl,’ and get back legitimate IP addresses. Overly paranoid? Probably, but here’s the fix:

# DNS servers for guest network
dhcp-option=tag:br1,6,208.67.222.222,208.67.220.220
# Domain name for guest network
dhcp-option=tag:br1,15,guest

This goes in Advanced > DHCP/DNS > Dnsmasq custom configuration. Combined with the iptables rules above, this will force your guests to not use the router’s DNS.

Once again, ‘br1’ is the guest bridge. You can also specify your own DNS servers instead of OpenDNS.

And there you have it – a secure network for your own devices and a guest network, carefully partitioned off from everything else, solely for Internet access.

There are two pitfalls with this setup: no bandwidth prioritization and the possibility that someone could do illegal things with your IP address.

I don’t really care about bandwidth, because I already have a QoS setup, and I live in a suburban neighborhood so users of my guest network will be few and far between.

However, I am considering forcing all my guest traffic through the Tor network. That may be a future post.

Windows: Combat Evolved: a Halo Satire

What would Microsoft’s Halo video game series be like if it involved Microsoft itself?

The Introduction

Halo tells the story of 26th century humanity, which has organized itself under the auspices of the United Nations Space Command (Microsoft). Humans are fighting a losing war against the Covenant (Apple), a theocratic collection of alien races that worship a long-dead alien species called the Forerunners (pre-2000 Macs). Already, many colony worlds, including the military stronghold Reach (IBM), have fallen.

In the Beginning

In the first game, Halo: Combat Evolved, a lone starship (Windows XP) crash lands on a mysterious Forerunner ringworld (Best Buy) that is thought to be some kind of superweapon. Its human survivors, including the superhuman cyborg Master Chief (Bill Gates), fight the Covenant for control of the ring (store). However, the Covenant accidentally release a zombie-like parasite known as the Flood (Android). It is discovered that the purpose of the halo is actually to cleanse the galaxy of all sentient life, thereby depriving the Flood of all possible infection vectors. The Chief then destroys the ring and its Flood infestation before returning to Earth (Redmond, Washington) to warn of an impending invasion by a new Covenant fleet (the Intel Macintosh).

The Story Continues

In the sequel, Halo 2, the Covenant locate and invade Earth. Despite a valiant defense by the UNSC Home Fleet and Earth’s orbital defense platforms (Windows Vista), a single Covenant carrier punches through and lands at New Mombasa, an African metropolis. With the Master Chief’s help, the UNSC destroys most of the initial assault. However, the carrier makes a hasty slipspace jump to Delta Halo, another halo installation (New Egg). The Covenant and the UNSC once again battle for control of it. Meanwhile, the Chief assassinates a key Covenant leader (Steve Jobs) and the Flood are once again released. This sets off a complicated chain of events that leads to the primary warrior race of the Covenant, the Elites (Mac OS X), seceding from the theocracy. They are opposed by the new warrior race, the Brutes (iOS).

The Elites make a temporary truce with the humans to stop the rest of the Covenant from firing the halo ring. They succeed, but all rings are put on standby, ready to fire remotely from a location known only as “the Ark” (Amazon). The remaining Covenant leadership plan to bring the entire fleet to Earth and uncover a major Forerunner artifact (iOS 7).

In one of the worst cliffhangers in gaming history, the Master Chief stows away and prepares to “finish the fight.”

Finish the Fight

Halo 3 opens with the Chief jumping from the ship and landing outside the ruins of New Mombasa. He helps the UNSC (Windows Phone 7) launch a last-ditch attack against the Covenant excavation site, but they fail to put a dent in the operation. The artifact is activated by the Covenant; it turns out to be a portal to the Ark (flat UI design). The Elites and the UNSC (Windows 7) follow the Covenant through the portal to stop them from once and for all. After an epic three-way battle, the Master Chief kills the Covenant leadership and blows up the Ark to eradicate the Flood. Unfortunately, his ship fails to make it back through the portal in one piece, and he is left stranded in unknown space.

A New Era

Halo 3 was followed years later by Halo 4, which is intended to begin a new Halo trilogy.

In Halo 4, the Master Chief crash-lands on a mysterious Forerunner planet called Requiem (Power Mac G4). The UNSC Infinity (Windows 8), a massive capital ship commissioned after the war with the Covenant, attempts a rescue mission, but instead finds itself trapped in Requiem’s gravity well. The Chief helps to free it, but accidentally releases an immensely powerful Forerunner warlord known as the Didact (Steve Wozniak). The Didact intends to take a Forerunner ship to Earth and wipe out humanity with the Composer (Mac OS), a Forerunner weapon that allows him to turn sentient beings into his own soldiers. However, he is stopped in the nick of time thanks to the efforts of the Chief and the Infinity.