|
| 1 | +# Basic Networking |
| 2 | + |
| 3 | +In this part we will go through some of basic Networking Concepts that is very related to how networking in zos working |
| 4 | + |
| 5 | +## Components |
| 6 | + |
| 7 | +- [Namespaces](<https://en.wikipedia.org/wiki/Linux_namespaces#Network_(net)>): As you may know linux have the concept of Namespaces which includes (users, net, ....) namespaces. which is basically considered as a full copy of the network stack that is fully isolated from the network stack of the machine |
| 8 | +- [Bridge](https://wiki.archlinux.org/title/network_bridge): A network bridge is a virtual network device that forwards packets between two or more network segments. A bridge behaves like a virtual network switch and works transparently. |
| 9 | +- veth: Virtual Ethernet (veth) pairs act like a cable connecting two endpoints. |
| 10 | + |
| 11 | +## What we are going to achieve in this doc |
| 12 | + |
| 13 | +We aim to create three network namespaces and establish connectivity between them using bridges and routing rules. Bridges operate at Layer 2, so they only broadcast packets to connected nodes without routing. |
| 14 | + |
| 15 | +- the file setup will looks like |
| 16 | +  |
| 17 | + |
| 18 | +## Steps |
| 19 | + |
| 20 | +### Creating the three namespaces |
| 21 | + |
| 22 | +``` |
| 23 | +sudo ip netns add lan1 |
| 24 | +sudo ip netns add lan0 |
| 25 | +sudo ip netns add lan2 |
| 26 | +``` |
| 27 | + |
| 28 | +for more info about `ip netns` check [this](https://man7.org/linux/man-pages/man8/ip-netns.8.html) |
| 29 | +so far we have this |
| 30 | + |
| 31 | + |
| 32 | + |
| 33 | +### Executing ip command for a specific namespace |
| 34 | + |
| 35 | +- if you did `ip a` command it will print the host interfaces, but will not print anything from any namespace |
| 36 | +- for example to execute `ip a` inside the lan0 namespace you need to do the following |
| 37 | + |
| 38 | +``` |
| 39 | +ip -n lan0 a |
| 40 | +``` |
| 41 | + |
| 42 | +- this will print the interfaces inside lan0 which now have only `lo` interface |
| 43 | +  |
| 44 | +- note that the first `ip a` command shows interfaces from the host, while the second one shows the interfaces inside the namespace. so the `lo` in the first command is not the same `lo` from the second command |
| 45 | +- to get a shell inside the namespace so we can execute commands directly inside the namespace without the need to specify the `-n lan0` each time we can do |
| 46 | + |
| 47 | +``` |
| 48 | +sudo ip netns exec lan0 bash |
| 49 | +``` |
| 50 | + |
| 51 | +- from the second command we see `lo` device is `DOWN` so to bring it up we do this inside lan0 namespace shell |
| 52 | + |
| 53 | +``` |
| 54 | +ip l set lo up |
| 55 | +``` |
| 56 | + |
| 57 | +### Creating the bridges |
| 58 | + |
| 59 | +do this in the host shell |
| 60 | + |
| 61 | +``` |
| 62 | +sudo ip l add br01 type bridge |
| 63 | +sudo ip l add br02 type bridge |
| 64 | +``` |
| 65 | + |
| 66 | +so far we have this |
| 67 | + |
| 68 | + |
| 69 | +to view the created bridges do `ip l` or `brctl show` |
| 70 | + |
| 71 | + |
| 72 | +from the above image you can see we have created the bridges but till now we don't have any attached interfaces |
| 73 | + |
| 74 | +### Connecting the wires |
| 75 | + |
| 76 | +- so far we have 3 namespaces and two bridges let's connect the wires between them |
| 77 | +- creating veth from `lan1` ns to `br01` bridge |
| 78 | +- Connecting a veth between br01 and lan1 |
| 79 | + |
| 80 | +``` |
| 81 | +sudo ip l add lan1 type veth peer name lan1br |
| 82 | +``` |
| 83 | + |
| 84 | +here if we executer `ip a` we will see something like the following |
| 85 | + |
| 86 | + |
| 87 | +the last two items shows we have link `16` and `17` those are the two ends of the veth that we created so lan1br1 <-> lan1 |
| 88 | + |
| 89 | +``` |
| 90 | +16: lan1br@lan1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop master br01 state DOWN group default qlen 1000 |
| 91 | + link/ether 46:13:d2:d2:b8:95 brd ff:ff:ff:ff:ff:ff |
| 92 | +17: lan1@lan1br: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000 |
| 93 | + link/ether 2e:de:7d:76:47:61 brd ff:ff:ff:ff:ff:ff |
| 94 | +``` |
| 95 | + |
| 96 | +the above command creates veth (link/cable) which have two ends one called `lan1` which we will connect later to `lan1` ns and the other end is `lan1br` which we will connect it later to the bridge `br01` |
| 97 | + |
| 98 | +- connect `lan1br` end to the bridge |
| 99 | + |
| 100 | +``` |
| 101 | +sudo ip l set lan1br master br01 |
| 102 | +``` |
| 103 | + |
| 104 | +- connect `lan1` end of the veth to `lan1` ns (basically move this end to lan1 ns) |
| 105 | + |
| 106 | +``` |
| 107 | +ip l set lan1 netns lan1 |
| 108 | +``` |
| 109 | + |
| 110 | +here we if exec `ip a` will find that lan1 end has been moved out of the host interfaces to the lan1 namespace and to see it exec `ip -n lan1 a` |
| 111 | + |
| 112 | + |
| 113 | +- note that the other end of lan1br is changed to if17 because lan1 is now in a different namesapce we can no longer reference it as lan1 otherwise it is referenced by `if17` which is a unique id generated by the kernel for lan1 also |
| 114 | +- also note that the other end of lan1 link in lan1 namespace is if16 which is lan1br but as long as it is not in the same namespace we can not reference it by this name so the unique id is used here |
| 115 | +- connecting another veth between br01 and lan0 same as above |
| 116 | + |
| 117 | +``` |
| 118 | +sudo ip l add lan0 type veth peer name lan0br |
| 119 | +sudo ip l set lan0br master br01 |
| 120 | +sudo ip l set lan0 netns lan0 |
| 121 | +``` |
| 122 | + |
| 123 | +- so far we have done this |
| 124 | + |
| 125 | + |
| 126 | + |
| 127 | +- and here is how it looks like if we did `ip a` in each namespace |
| 128 | + |
| 129 | + |
| 130 | + |
| 131 | +- as you can see everything now is in `DOWN` state let's turn on all of this |
| 132 | + |
| 133 | +``` |
| 134 | +sudo ip -n lan0 l set lan0 up # the end in the namespace |
| 135 | +sudo ip -n lan0 a a 10.10.1.1/24 dev lan0 # assign ip |
| 136 | +sudo ip l set lan0br up # the end in the bridge |
| 137 | +sudo ip -n lan1 l set lan1 up # lan1 ifc in lan1 namespace |
| 138 | +sudo ip -n lan1 a a 10.10.1.2/24 dev lan1 |
| 139 | +sudo ip l set lan1br up |
| 140 | +sudo ip l set br01 up # the bridge |
| 141 | +``` |
| 142 | + |
| 143 | +lets have a look on the routing table in the name space for example lan1 |
| 144 | + |
| 145 | +``` |
| 146 | +sudo ip -n lan1 r |
| 147 | +``` |
| 148 | + |
| 149 | + |
| 150 | + |
| 151 | +here we will find a route rule automatically added which says any packet that needs to be sent to any ip with `10.10.1.0/24` will go through `lan1` interface and this happened because we assigned it an ip in that range |
| 152 | +note:- till now we can not route any packets out side that range, we don't have a default gw yet |
| 153 | + |
| 154 | +- now lets do the same for connecting br01 with lan0 and lan2 |
| 155 | + |
| 156 | +``` |
| 157 | +sudo ip l add lan2 type veth peer name lan2br |
| 158 | +sudo ip l add lan02 type veth peer name lan02br |
| 159 | +sudo ip l set lan2br master br02 |
| 160 | +sudo ip l set lan2 netns lan2 |
| 161 | +
|
| 162 | +sudo ip l set lan02br master br02 |
| 163 | +sudo ip l set lan02 netns lan0 |
| 164 | +
|
| 165 | +sudo ip l set lan02br up |
| 166 | +sudo ip l set lan2br up |
| 167 | +sudo ip l set br02 up |
| 168 | +sudo ip -n lan0 l set lan02 up |
| 169 | +sudo ip -n lan2 l set lan2 up |
| 170 | +
|
| 171 | +# assign ip for lan02 in lan0 namespace |
| 172 | +sudo ip -n lan0 a a 10.10.2.1/24 dev lan02 |
| 173 | +sudo ip -n lan2 a a 10.10.2.2/24 dev lan2 |
| 174 | +``` |
| 175 | + |
| 176 | +#### so far we have this |
| 177 | + |
| 178 | + |
| 179 | + |
| 180 | +this means from lan0 ns I can reach lan1 ns and lan2, but till now we can not reach lan1 from lan2, because we only now have the bridges without any special routing rules (default gw is not set yet). so the bridge now is broadcasting the packets on all directly connected devices and the node that this data is for will pick it |
| 181 | + |
| 182 | +### Testing connectivity |
| 183 | + |
| 184 | +if the following ping examples didn't work for you, this maybe a firewall issue try doing this |
| 185 | + |
| 186 | +``` |
| 187 | +sudo iptables --policy FORWARD ACCEPT |
| 188 | +sudo ip netns exec lan0 echo 1 > /proc/sys/net/ipv4/ip_forward # enable ip forwarding |
| 189 | +``` |
| 190 | + |
| 191 | +- ping lan1 ns from lan0 |
| 192 | + |
| 193 | + |
| 194 | + |
| 195 | +- ping lan0 from lan2 |
| 196 | + |
| 197 | + |
| 198 | + |
| 199 | +- ping lan2 from lan1 (will not work) |
| 200 | + |
| 201 | + |
| 202 | + |
| 203 | +### Establishing connectivity between lan1 and lan2 |
| 204 | + |
| 205 | +- Adding a rule to lan1 ns to route to lan2 |
| 206 | + |
| 207 | +``` |
| 208 | +sudo ip -n lan1 r a 10.10.2.0/24 via 10.10.1.1 |
| 209 | +``` |
| 210 | + |
| 211 | +- this means if lan1 namespace wants to send any packets to 10.10.2.0/24 range we direct it to `lan0` ns and lan0 namespace is directly connected to lan2 |
| 212 | + |
| 213 | +- Note: ping lan2 from lan1 still not working but now we have a different error message `Destination host unreachable` and you will find it already tried to send the ping request many times instead of the previous error `Network is unreachable` because this time we know we should go through lan1 but we don't guarantee the packet will reach the other end |
| 214 | +- Configuring the other way around |
| 215 | + |
| 216 | + so far we taught the packet how to go from lan1 to lan2 but we didn't configure the other way from lan2 to lan1 to get a response |
| 217 | + |
| 218 | +``` |
| 219 | +sudo ip -n lan2 r a 10.10.1.0/24 via 10.10.2.1 |
| 220 | +``` |
| 221 | + |
| 222 | +now we have all connected. so we can ping lan1 from lan2 and lan2 from lan1 |
| 223 | + |
| 224 | +### NATting |
| 225 | + |
| 226 | +if we did inspect to the packets sent during ping. lets say for example we are doing ping from lan1 to lan2 and we did `tcpdump` on lan2 namespace |
| 227 | + |
| 228 | +``` |
| 229 | + sudo ip netns exec lan1 ping 10.10.2.2 # ping lan2 from lan1 |
| 230 | +``` |
| 231 | + |
| 232 | + |
| 233 | + |
| 234 | +- Here we see the requests are coming from 10.10.1.2 while in our case we deal with lan0 as a router so in lan0 we can add natting rules so the requests are sent to lan2 as if it is from lan0 without lan2 knows lan1 is the one who is sending the request. |
| 235 | + |
| 236 | +- In this case lan0 will change the source MAC and IP to it's interface ip which is 10.10.2.1 and sent to lan2 and lan2 will reply to lan0 then lan0 will forward the reply to lan1 |
| 237 | + |
| 238 | +``` |
| 239 | +sudo ip netns exec lan0 nft add table nat |
| 240 | +sudo ip netns exec lan0 nft 'add chain nat postrouting { type nat hook postrouting priority 100 ; }' |
| 241 | +sudo ip netns exec lan0 nft add rule nat postrouting masquerade |
| 242 | +``` |
| 243 | + |
| 244 | +now lan0 works as a router |
| 245 | + |
| 246 | + |
| 247 | +we can now remove the routing rules that we created before and only create a default gw rule in lan1 and lan2 |
| 248 | + |
| 249 | +``` |
| 250 | +# remove old routing rules |
| 251 | +sudo ip -n lan1 r d 10.10.2.0/24 |
| 252 | +sudo ip -n lan2 r d 10.10.1.0/24 |
| 253 | +# create default gw |
| 254 | +sudo ip -n lan1 route add default via 10.10.1.1 dev lan1 |
| 255 | +sudo ip -n lan2 route add default via 10.10.2.1 dev lan2 |
| 256 | +``` |
0 commit comments