3 Essential Linux Networking Commands

Here at Question Computer we do a fair amount of lab creation, especially with Linux and networking. I’d like to share my essential commands that I use for setting up a basic IP network since in most of my articles I assume that part is already set up.

Stand aside, ifconfig (it’s been deprecated). iproute2 is the official utility to interact with the Netlink Linux kernel interface, which provides a way for the Linux kernel’s networking stack to be configured. That’s a bit of a long-winded way of saying if you want an IP address, use iproute2. iproute2 is split up into a number of different child commands, each for a different part of the network stack, such as ip addresses, interfaces, routing, etc.

Keep in mind – iproute2 manages Linux network configurations on the fly. If you want your configurations to survive a reboot, you’ll either need to write a startup script or you can use the Ubuntu tool for managing network configs – netplan.

Topology

We’ll be working with a basic topology that will illustrate the different commands we’ll be using here. By the end of the lab, we should have IP connectivity between all nodes. Ubuntu20.04-2 and Ubuntu20.04-3 will be serving as routers by forwarding and have it enabled in their /etc/sysctl.conf files.

1. ip link

We’ll start with Ubuntu20.04-1 at the bottom left. Before we can even get to assigning IP addresses, we need to know what the interfaces are called, and to turn them on. The ip link command will show us what they are:

ip link
---

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 0c:96:94:ff:00:00 brd ff:ff:ff:ff:ff:ff

We can ignore the “lo” loopback interface, the one that is connected to the actual network is “ens3”. Let’s enable it:

ip link set ens3 up

Now that it’s enabled, we can assign an IP address to this interface. This command will need to be run on all interfaces on all nodes. I won’t show that, as it’s a bit repetitive. It can be run either before or after an IP address is assigned, but I like to do it before.

2. ip address

To assign an IP address to Ubuntu20.04-1’s ens3 interface, this command will do it:

ip address add 192.168.0.2/24 dev ens3

Hopefully the arguments there are pretty self-explanatory. “add” means we’re adding an IP address, and “dev” just means we’re assigning the address to the interface that comes after it.

Now that we know how to assign an IP address, the rest of the nodes are easy.

Ubuntu20.04-2:

ip address add 192.168.0.1/24 dev ens3
ip address add 10.0.0.1/30 dev ens4

Ubuntu20.04-3:

ip address add 172.16.0.1/24 dev ens3
ip address add 10.0.0.2/30 dev ens4

Ubuntu20.04-4:

ip address add 172.16.0.2/24 dev ens3

3. ip route

The way to manage routes with iproute2 is with the ip route command.

First, on Ubuntu20.04-1, we’ll need to add a default route which is the most common basic configuration for an endpoint node. This command will add it:

ip route add default via 192.168.0.1

The via parameter allows you to specify where to send traffic that is being sent using the default route. In this case, it’s the Ubuntu router at the top left, Ubuntu20.04-2.

Ubuntu20.04-2 is directly connected to 192.168.0.0/24 and 10.0.0.0/30 with interfaces ens3 and ens4, but it does not know about 172.16.0.0/24. Adding a static route for that subnet pointing to 10.0.0.2 (the other Ubuntu router at the top right) will allow traffic to flow:

ip route add 172.16.0.0/24 via 10.0.0.2

A similar but mirror image of that command can be run on Ubuntu20.04-3:

ip route add 192.168.0.0/24 via 10.0.0.1

And finally we’ll add another default to Ubuntu20.04-4:

ip route add default via 172.16.0.1

All connectivity should be in place!

Verify

Let’s try to ping from Ubuntu20.04-1 to Ubuntu20.04-4, all the way across the environment.

From Ubuntu20.04-1:

ping 172.16.0.2
---

PING 172.16.0.2 (172.16.0.2) 56(84) bytes of data.
64 bytes from 172.16.0.2: icmp_seq=1 ttl=62 time=1.97 ms

It works! Ping is a simple but handy tool. Always remember that when you get a reply, it means not only did traffic make it to its destination, but it came back too.

Telnet to Ubuntu Server 20.04 in GNS3 Instead of VNC

If you’re using Ubuntu VM’s inside of GNS3, you’re probably sick of using a VNC client to access its command line.

The first big drawback to using VNC is that you can’t (or at least it’s not immediately obvious how to) paste text or commands you’ve found into the terminal. You have to retype everything, which is a real bummer.

The second big drawback is that a VNC session can’t be automated (or at least I don’t know of a good tool to do that). Since VNC is like RDP in that the session is visual, a human being or really advanced AI is required to interact with the session.

Having access to a VM in GNS3 via telnet to its terminal is a real benefit. You can set it up pretty quickly in Ubuntu 20.04. Full disclosure – this method only gets you access after the device has booted and arrived at the login prompt. There is a way to allow access earlier than that so the boot process can be viewed, I just haven’t gotten to it yet.

Set your VM to not be “linked base”

One mistake I often make in GNS3 is forgetting to make my VM not a “linked base” when I want to make permanent changes. A linked base is basically a clone of your VM. Any changes you make, files you download or programs you install will be blown away when you delete the device from the GNS3 canvas. To disable this functionality temporarily to make permanent changes, go to the device in the left pane and click “configure template”. On the advanced tab, uncheck “Use as a linked base VM”:

When you are done configuring the telnet capability, you can recheck this box. All linked base VM’s you drag out afterwards will have the telnet capability.

Create the ttyS0.service

You first need to create a systemd service for serial access. We need to create a file called ttyS0.service in the /lib/systemd/system/ directory:

vi /lib/systemd/system/ttyS0.service

The file contents should look like this:

[Unit]
Description=Serial Console Service

[Service]
ExecStart=/sbin/getty -L 115200 ttyS0 vt102
Restart=always

[Install]
WantedBy=multi-user.target

getty is program that manages tty sessions, physical or virtual terminals. It will run the login prompt when a connection is detected. 115200 is the baud rate, ttyS0 is a device file that points to the current terminal, and vt102 is the terminal emulator.

Load the service in systemd

Just a few commands will load the new service in systemd, and the script will run on boot to activate your serial device and allow telnet. Run these commands:

#Make file executable
chmod 755 ttyS0.service

#Reload systemd
systemctl daemon-reload

#Enable the service
systemctl enable ttyS0

#Start the service
systemctl start ttyS0

Your service is good to go!

Change the console type to telnet

You need to first shut down your VM so you can change the console type. Once it’s shutdown, you can configure the device on the canvas, or the template in the pane to the left, or both. The template will make changes for all VM’s dragged onto the canvas in the figure. Either way, configure the node by right clicking on it, and clicking on “configure” or “configure template”. At the very bottom, you should see a dropdown for “console type”. Change it to “telnet”:

Log in via telnet!

Just double-click on your VM. You won’t see any output on the telnet window while the VM is booting up because the service hasn’t fired yet. But when it does, you should see the login prompt:

Bonus tip – turn off dhcp in netplan

I had to turn off dhcp in Ubuntu’s netplan network configuration tool to get it to stop hanging at boot. There should be a yaml file in /etc/netplan/ (the yaml file name might differ per system) where you can turn it off. My netplan config looks like this:

network:
  ethernets:
    ens3:
      dhcp4: false
      optional: yes
  version: 2

Hope that helps!

Strongswan IPSec Mediation – Both Ubuntu Linux 20.04 Peers Behind Cisco NAT

Background

Strongswan is an open source project that implements the IKE protocol which is used for cryptographic key negotiation in the IPSec standard protocol. IPSec is used to build an encrypted network connection between two points on a network, usually the Internet but not always.

Most often, the two points where the encryption and decryption are happening know about each other’s IP address, on the Internet that means they have publicly routable IP addresses. IPSec has a built-in mechanism to handle the scenario if one of these points does not have an a public routable IP address, this is called NAT-Traversal. It looks something like this:

POINT A —> NAT ROUTER —> INTERNET —> POINT B

Point A must initiate the connection to Point B because it has a private IP address (10.x and the like) and that’s the only way the NAT router will let the connection through.

But what if BOTH peers are behind NAT routers with private IP addresses? Something like this:

POINT A —> NAT ROUTER —> INTERNET —> NAT ROUTER —> POINT B

Private-peer-to-private-peer connectivity is established in other network protocols such as VoIP using some sort of 3rd party mediator that performs a trick called UDP hole-punching, where both peers are told by the mediator the public IP address of the NAT Router that is in front of the peer they are trying to connect to. For VoIP this is usually a STUN server. Both peers attempt a connection at the same time, the NAT Routers write translations for the peers, and a connection is built.

While this technique is pretty ancient and many applications implement it, there is not a standard way to do it for IPSec. Strongswan, it seems, has a little known feature for IPSec peer mediation that allows for peer to peer NAT Traversal similar to STUN in VoIP. This feature requires that a third device have a public IP (can’t escape a public IP somewhere in the equation) and running the Strongswan mediation service. It only works with strongswan, although an RFC draft was created back in 2008 in the hopes that mediation for IPSec would be standardized.

Topology

The two Ubuntu 20.04 IPSec peers are both behind Cisco IOSv routers running a basic NAT in Port Address Translation (PAT) mode, which is a tcp/udp port-based one-to-many NAT that is running by default on many consumer routers and is the way the many devices today connect to the Internet. In other words, 192.168.0.3 can not ping 172.16.0.3, and vice versa. But they can both ping 13.0.0.2, where our secret weapon is located, the Strongswan IKE Mediator.

Installation

Installing Strongswan on Ubuntu 20.04 is easy as pie:

apt-get install strongswan

Configuration

UbuntuServer20.04-1

First edit /etc/ipsec.conf

config setup
conn %default
        ikelifetime=60m
        keylife=20m
        rekeymargin=3m
        keyingtries=1
        keyexchange=ikev2
        mobike=no
        dpdaction=restart
        dpddelay=60s
        left=%defaultroute
        leftfirewall=yes

conn medsrv
        leftid=bob@questioncomputer.com
        leftauth=psk
        right=13.0.0.2
        rightid=mediator@questioncomputer.com
        rightauth=psk
        mediation=yes
        authby=secret
        auto=start

conn peer
        leftid=bob@questioncomputer.com
        leftauth=psk
        leftsubnet=192.168.0.0/24
        right=%any
        rightid=alice@questioncomputer.com
        rightsubnet=172.16.0.0/24
        rightauth=psk
        authby=secret
        mediated_by=medsrv
        auto=start

Then edit /etc/ipsec.secrets to put your PSK in there:

mediator@questioncomputer.com : PSK "james"
bob@questioncomputer.com : PSK "james"
alice@questioncomputer.com : PSK "james"

UbuntuServer20.04-2

First edit /etc/ipsec.conf

conn %default
        ikelifetime=60m
        keylife=20m
        rekeymargin=3m
        keyingtries=1
        keyexchange=ikev2
        mobike=no
        dpdaction=restart
        dpddelay=60s
        left=%defaultroute
        leftfirewall=yes
conn medsrv
        leftid=alice@questioncomputer.com
        leftauth=psk
        right=13.0.0.2
        rightid=mediator@questioncomputer.com
        rightauth=psk
        mediation=yes
        auto=add

conn peer
        leftid=alice@questioncomputer.com
        leftauth=psk
        leftsubnet=172.16.0.0/24
        right=%any
        rightid=bob@questioncomputer.com
        rightsubnet=192.168.0.0/24
        rightauth=psk
        mediated_by=medsrv
        authby=secret
        auto=start

Then edit /etc/ipsec.secrets to put your PSK in there:

mediator@questioncomputer.com : PSK "james"
bob@questioncomputer.com : PSK "james"
alice@questioncomputer.com : PSK "james"

Mediator (UbuntuServer20.04-4)

First edit /etc/ipsec.conf

conn %default
        ikelifetime=60m
        keylife=20m
        rekeymargin=3m
        keyingtries=1
        keyexchange=ikev2
        mobike=no
        dpdaction=clear
        dpddelay=60s

conn medsrv
        left=13.0.0.2
        leftid=mediator@questioncomputer.com
        leftauth=psk
        leftfirewall=yes
        right=%any
        rightauth=psk
        mediation=yes
        authby=secret
        auto=add

Then edit /etc/ipsec.secrets

mediator@questioncomputer.com : PSK "james"<br>bob@questioncomputer.com : PSK "james"<br>alice@questioncomputer.com : PSK "james"

Make sure to issue this on all three to load your configs:

ipsec restart

Verification

A healthy connection can be checked with the ‘ipsec’ command:

root@u2004:/home/james/strongswan# ipsec statusall
Status of IKE charon daemon (strongSwan 5.9.0, Linux 5.4.0-29-generic, x86_64):
  uptime: 103 minutes, since Oct 08 19:38:24 2020
  malloc: sbrk 1748992, mmap 0, used 902656, free 846336
  worker threads: 11 of 16 idle, 5/0/0/0 working, job queue: 0/0/0/0, scheduled: 14
  loaded plugins: charon agent connmark eap-mschapv2 aes des rc2 sha2 sha3 sha1 md5 mgf1 random nonce x509 revocation constraints pubkey pkcs1 pkcs7 pkcs8 pkcs12 pgp dnskey sshkey pem openssl fips-prf gmp curve25519 chapoly xcbc cmac hmac gcm drbg attr kernel-netlink resolve socket-default socket-dynamic stroke vici updown xauth-generic lookip error-notify addrblock unity counters
Listening IP addresses:
  192.168.0.3
Connections:
      medsrv:  %any...13.0.0.2  IKEv2, dpddelay=60s
      medsrv:   local:  [left@questioncomputer.com] uses pre-shared key authentication
      medsrv:   remote: [mediator@questioncomputer.com] uses pre-shared key authentication
      medsrv:   child:  dynamic === dynamic TUNNEL, dpdaction=restart
        peer:  %any...%any  IKEv2, dpddelay=60s
        peer:   local:  [left@questioncomputer.com] uses pre-shared key authentication
        peer:   remote: [right@questioncomputer.com] uses pre-shared key authentication
        peer:   child:  192.168.0.0/24 === 172.16.0.0/24 TUNNEL, dpdaction=restart
Security Associations (2 up, 0 connecting):
        peer[6]: ESTABLISHED 2 minutes ago, 192.168.0.3[left@questioncomputer.com]...12.0.0.2[right@questioncomputer.com]
        peer[6]: IKEv2 SPIs: 400da3c783ad093d_i 35869903e6803225_r*, pre-shared key reauthentication in 52 minutes
        peer[6]: IKE proposal: AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/ECP_256
        peer{10}:  INSTALLED, TUNNEL, reqid 1, ESP in UDP SPIs: c01b6c68_i c56e26d5_o
        peer{10}:  AES_CBC_128/HMAC_SHA2_256_128, 0 bytes_i, 0 bytes_o, rekeying in 12 minutes
        peer{10}:   192.168.0.0/24 === 172.16.0.0/24
      medsrv[3]: ESTABLISHED 49 minutes ago, 192.168.0.3[left@questioncomputer.com]...13.0.0.2[mediator@questioncomputer.com]
      medsrv[3]: IKEv2 SPIs: 127a15068a32e07f_i* 703cba84aa11f49e_r, pre-shared key reauthentication in 2 minutes
      medsrv[3]: IKE proposal: AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/ECP_256

You’ll be looking to see that both the “medsrv” and “peer” connections are in an “Established” state.

And of course as always, make sure you ping across the tunnel to make sure it works.

As an added bonus, I was able to ping through the tunnel from l92.168.0.3 to the Cisco NAT Router at 172.16.0.1, I just need to add a route on the Cisco NAT Router by issuing “ip route 192.168.0.0 255.255.255.0 172.16.0.3”.

Troubleshooting

The log file where most logs go in Ubuntu is at ‘/var/log/syslog’, grepping for “charon” will help you sort them:

root@u2004:/home/james/strongswan# tail /var/log/syslog | grep charon
Oct  8 21:28:41 u2004 charon: 13[NET] sending packet: from 192.168.0.3[4500] to 12.0.0.2[4500] (80 bytes)
Oct  8 21:28:41 u2004 charon: 16[NET] received packet: from 12.0.0.2[4500] to 192.168.0.3[4500] (80 bytes)
Oct  8 21:28:41 u2004 charon: 16[ENC] parsed INFORMATIONAL response 8 [ ]

And as usual, do a packet capture to see if the two peers are trying to build a connection to each other. If packets are not being generated or dropped somewhere, you’ll know where to look for a problem. You can filter for “isakmp” packets to narrow things down:

In the above image you can see there is a connection between the NAT routers 11.0.0.2 and 12.0.0.2, but also connections to the mediator at 13.0.0.2.