Unix: networking from scratch blog
This commit is contained in:
parent
5ddaa5e385
commit
ac3c7da562
1 changed files with 257 additions and 0 deletions
257
src/content/unix/networking-from-scratch.md
Normal file
257
src/content/unix/networking-from-scratch.md
Normal file
|
@ -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: <LOOPBACK,UP,LOWER_UP> 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: <BROADCAST,MULTICAST> 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: <BROADCAST,MULTICAST> 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
|
||||
`<BROADCAST,MULTICAST>` 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: <BROADCAST,UP,MULTICAST> 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
|
||||
```
|
Loading…
Reference in a new issue