diff --git a/src/content/unix/networking-from-scratch.md b/src/content/unix/networking-from-scratch.md new file mode 100644 index 0000000..d1ad660 --- /dev/null +++ b/src/content/unix/networking-from-scratch.md @@ -0,0 +1,257 @@ +--- +title: 'Networking from Scratch' +description: 'Setup your own simple network on Linux' +updateDate: 'Apr 22 2024' +--- + +# Why learn Low-Level Networking? + +Networking is one of the most complicated and practical standards for ever +created for digital communication. This unfortunately means that when we connect +to a network, it's quite hard to understand what's actually happening and +knowing this is very helpful for debugging. + +In this article we'll go through setting up a simple wired network using the +`ip` tool on Linux. We'll also do a quick overview of next steps. + +You only need one Linux computer, but it's much more fun if you have two. You'll +also want an Ethernet cable connecting the two Linux machines. + +## Setting Up + +By default, your Linux computer almost certainly uses a network manager. This is +a program that does what we're about to do automatically. You should never have +more than one network manager running at a time, so if we're acting as one, +you'll need to turn yours off. + +```bash +systemctl disable NetworkManager.service +systemctl disable systemd-networkd.service +``` + +It's okay if one of those errors. Next, to clear the configuration those network +manager provided, you'll need to reboot with `systemctl reboot`. + +Further, put the following alias in your `~/.bashrc` or whichever file your +shell uses: + +```bash +alias ip='ip -c' # Makes output colorful +``` + +# Background of Networking + +## IP Addresses + +A computer can have multiple network interfaces. Most often these will be one +of: + - A WIFI card + - An Ethernet port + - A USB to Ethernet adapter + +Each interface can be assigned IP addresses. These addresses come in one of two +flavours: IPv4 and IPv6. Version 4 is the old standard that's used almost +universally. Version 6 came out in 1996 and improves on IPv4 by adding more +addresses (IPv4 only has about 4.3 billion... these ran out in 2010). +Unfortunately, IPv6 adoption is one of the slowest updates in the history of +computing, so IPv4 remains more commonly used, with many home networks not even +offering IPv6. + +An IPv4 address is 32bits, represented by decimal numbers in groups of 8bits, +with dots in between. This means each of the four numbers range from 0-255 +inclusive. Here are some examples: + +``` +127.0.0.1 +10.0.0.0 +10.42.43.250 +``` + +An IPv6 address is 128bits, represented by hexadecimal numbers, in groups of +16bits, with colons in between. Two consecutive colons can be used to indicate +filler zeros. Here are some examples: + +``` +fd00:1bac:c0ca:12a2:1a7e:b9ff:fe07:d7a2 +2001:0db8:85a3:0000:0000:8a2e:0370:7334 +2001:0db8:85a3:0:0:8a2e:0370:7334 +2001:0db8:85a3::8a2e:0370:7334 +``` + +We will use IPv4 for the convenience, but the concepts transfer quite directly +to IPv6. + +## Subnet Masks + +A network mask is used to figure out which IP addresses belong to a network. +This is specified as the number of bits in a slash after the IP address. + +For example `192.168.1.7/24` means the netmask is the first 24 bits of this IPv4 +address. Remember, that each number represents 8 bits, so we can convert this +address to: + +``` + 192 . 168 . 1 . 7 + 11000000 10101000 00000001 00000111 +└─────────────┬────────────┘ + First 24 bits +``` + +In this case, that means the last of the four numbers can be anything, and the +IP address will be considered as part of this network. Some examples: + - `192.168.1.0` + - `192.168.1.255` + - `192.168.1.127` + - `192.168.1.100` + +In total, there are 256 addresses on this network. The largest "block" reserved +for private use is `10.0.0.0/8`. This network has about 16.7 million addresses! + +``` + 10 . 0 . 0 . 0 + 00001010 00000000 00000000 00000000 +└────┬───┘ +First 8 bits +``` + +# The Address Table + +## Parsing the Address Table + +Use `ip address` or `ip addr` or `ip a` to display your address table. It should +look something like: + +``` +1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 + link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 + inet 127.0.0.1/8 scope host lo + valid_lft forever preferred_lft forever + inet6 ::1/128 scope host noprefixroute + valid_lft forever preferred_lft forever +2: eth0: mtu 1500 qdisc mq state UP group default qlen 1000 + link/ether 18:7e:a9:47:e2:c7 brd ff:ff:ff:ff:ff:ff +3: wlan0: mtu 1500 qdisc noop state DOWN group default qlen 1000 + link/ether 3c:22:ff:b8:27:a1 brd ff:ff:ff:ff:ff:ff +``` + +Let's go through this output. Firstly, we see there are three interfaces on this +computer. Their names are `lo`, `eth0`, and `wlan0`. Typically, interfaces +starting with an `e` are wired and those starting with `w` are wireless (WIFI). + +`lo` is the loopback interface. This isn't a real interface, but your computer +uses it to send network messages to itself. We can see its IPv4 address in the +`inet` line is `127.0.0.1` with a subnet mask of `8`. In the `inet6` line, we +see it has an IPv6 of `::1` with subnet mask `128`. This is true for all Linux +computers, so you should see the same thing. + +`eth0` is an Ethernet port on my computer. The lack of an `UP` in the +`` means that the interface isn't currently communicating +with anything. On the `link/ether` line, we see the MAC address of this +interface. `eth0` currently doesn't have any IP addresses assigned to it, so the +`inet` and `inet6` lines are missing. + +`wlan0` has a similar situation with `eth0`, in that it doesn't have any +addresses yet. + +## Adding an Address + +You will need `sudo` for any `ip` commands which modify the network tables. I +will omit the `sudo` from here on. + +Let's add an IP address of `10.42.43.20/24` and `10.42.43.100/24` to `eth0`: + +```bash +ip a add 10.42.43.20/24 dev eth0 +ip a add 10.42.43.100/24 dev eth0 +``` + +Now the address table should show these addresses: + +``` +... +2: eth0: mtu 1500 qdisc mq state UP group default qlen 1000 + link/ether 18:7e:a9:47:e2:c7 brd ff:ff:ff:ff:ff:ff + inet 10.42.43.20/24 brd 10.42.43.255 scope global eth0 + valid_lft forever preferred_lft forever + inet 10.42.43.100/24 brd 10.42.43.255 scope global eth0 + valid_lft forever preferred_lft forever +... +``` + +As a challenge, try adding an IPv6 address! + +# The Routing Table + +Routing tables determine where your computer will send network messages (known +as packets). This is very important in determining which interface to send a +packet over and using the loopback when possible. + +Say we have two interfaces with the following addresses: + - `eth0`: `10.42.43.20/24` + - `wlan0`: `192.168.0.4/24` + +If we want to send the packet to IP address `10.42.43.30`, the computer will +make sure to use `eth0`. + +In a more complicated case, consider: + - `eth0`: `10.42.43.20/24` + - `wlan0`: `10.42.43.21/8` + +Sending to IP `10.42.40.1` clearly must go through interface `wlan0`, but what +about a packet to `10.42.43.1`? Both interfaces can legally send this packet, as +their subnetworks both contain the address `10.42.43.1`. To determine which one +to use, your computer will check the routing table. + +## Parsing the Routing Table + +You can view your routing table with `ip route` or `ip r`. Your routing table +might look like the this right now: + +``` +10.42.43.0/24 dev eth0 kernel scope link src 10.42.43.100 +10.42.43.0/24 dev eth0 kernel scope link src 10.42.43.20 +``` + +According to the routing table above, any packets sent to `10.42.43.0/24` will +have the `10.42.43.100` IP address in their header, when sent from `eth0`. +That's since it appears higher in the routing table. + +## Setting routes + +Adding a route is very similar to typing exactly what you want to see in the +routing table: + +``` +ip r add 10.42.43.0/24 dev eth0 +``` + +You can also remove routes, which is helpful if you don't want a certain +interface sending packets: + +``` +ip r del 10.42.43.0/24 dev eth0 +``` + +The last important route is the "default" route. Often this is called the +"default gateway" in network managers. This is the route used when the IP you're +trying to reach isn't on one of the subnetworks you're connected to. It's really +the "internet". + +``` +ip r add default via 10.42.42.1 dev eth0 +``` + +This means that when your computer can't find a matching subnetwork in the +routing table, it'll send the packet over to `10.42.43.1` using interface +`eth0`. Assuming `10.42.43.1` is setup for packet forwarding and has internet +access, this will give your computer internet access as well! + +Default routes are confusingly listed at the top of the routing table, but +they're used in order (top to bottom) only after all the subnets have been +checked. + +``` +default via 10.42.43.1 dev eth0 +10.42.43.0/24 dev eth0 kernel scope link src 10.42.43.100 +10.42.43.0/24 dev eth0 kernel scope link src 10.42.43.20 +```