networkingLinux.png

Networking with Linux: commands, services and more

In this post, we are going to study different commands to know, create, modified and test our network on Linux. There are a great variety of them. I’m going to be using an Ubuntu server to explain most of them, but they can be used on Debian, RHEL and more.


arp & ip neigh

Address Resolution Protocol. It is used to manipulate the ART table storage in our server:

$ arp
Address                  HWtype  HWaddress           Flags Mask            Iface
10.1.0.28                ether   c8:94:02:62:c3:89   C                     wlo1
_gateway                 ether   c8:f6:22:6b:19:80   C                     wlo1
10.1.0.28                ether   c8:94:f2:6d:23:89   C                     eno2
10.1.0.7                 ether   03:42:2a:00:a0:07   C                     eno2
10.1.0.20                ether   ff:4d:a2:e3:af:57   C                     wlo1                    
10.1.0.2                 ether   e4:8d:ac:87:ff:d3   C                     eno2

You can see the entries for a specific interface using -i:

$ arp -i eno2

To add an entry (permanently) to the cache, use the “-s" option. You need to specify the IP and MAC addresses, as well as the interface. Seen here:

$ arp -s 10.1.0.96 -i ethX 51:53:00:17:34:09

Removing an entry:

$ arp -d 10.1.0.96

Linux ip neigh it’s a new version of arp command. The usage is the same:

$ ip neigh 
10.1.0.28 dev wlo1 lladdr c8:94:02:6d:c3:49 STALE
10.1.0.1 dev wlo1 lladdr c8:b4:22:93:19:80 STALE
10.1.0.28 dev eno2 lladdr c8:94:12:6d:c3:89 STALE
fe80::ca24:22ff:fe2b:1980 dev eno2 lladdr c8:b4:22:9b:19:80 router STALE
fe20::hb4:22ff:fe2b:1980 dev wlo1 lladdr c8:b4:22:9b:19:80 router STALE

To add a new entry to the table using the ip command, use the following:

$ ip neigh add 10.1.0.96 dev ethX

To delete an existing entry from the table, use the following:

$ ip neigh del 10.1.0.96 dev ethX

So, why use ip neigh instead of arp? Because arp come with the net-tools package. This package is no longer actively developed, and most of those tools have been deprecated in favor of their ip equivalents.


curl & wget

This two command are used to transfer files via terminal. With curl, you can see an entire website:

$ curl https://blog.matiasmercado.ar

You can download a file with curl using “-O” argument:

$ curl -O https://www.google.com/logos/doodles/2022/quinos-90th-birthday-6753651837109466-2x.png

With wget you can download a file too:

$ wget https://www.google.com/logos/doodles/2022/quinos-90th-birthday-6753651837109466-2x.png

We can use wget with the argument “-b” to make a background download:

$ wget -b https://www.google.com/logos/doodles/2022/quinos-90th-birthday-6753651837109466-2x.png

But you can also upload things, like in my post to upload via terminal:

https://blog.matiasmercado.ar/archives/27
$ curl --upload-file "file"  https://transfer.sh/"file name"

There’s a world of thing you can play with curl, and that involves the HTTP codes. For example, you can test if a page it’s ok by trying to get a 200 HTTP code “OK”, try:

$ curl --write-out "%{http_code}\n" --silent --output /dev/null https://blog.matiasmercado.ar
200

You can make an easy script to detect the status of websites:

#!/bin/bash -e

## You need to add your sites to list.txt to be checked 
## Status code for http: 200= OK. 400= Bad Request. 404= Not found 
## You can check all the status codes here: 
## https://developer.mozilla.org/es/docs/Web/HTTP/Status 

while read line; do
   response=$(curl --write-out "%{http_code}\n)" --silent --output /dev/null "$line")
   echo $line: $response
done < list.txt

Follow my previous post to get more info about scripting on bash

https://blog.matiasmercado.ar/archives/497

dig

dig is a flexible tool for interrogating DNS servers. Performs DNS lookup and displays the answers that are returned from the name server that were queried. It’s the most used tool used by DNS administrators to troubleshoot DNS problems.

The syntax of dig is simple:

dig "@server" "name" "type"
$ dig matiasmercado.ar

; <<>> DiG 9.16.1-Ubuntu <<>> matiasmercado.ar
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 63820
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;matiasmercado.ar.		IN	A

;; ANSWER SECTION:
matiasmercado.ar.	3600	IN	A	45.227.160.40

;; Query time: 307 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Jul 20 17:53:53 -03 2022
;; MSG SIZE  rcvd: 61

I’m using pi-hole as my primary DNS, here I set up 10.1.0.7 as my Jellyfin server with the local domain name jellyfin.ar. Using dig, I can test if in my default DNS I can find this domain linked to the IP:

$ dig jellyfin.ar

; <<>> DiG 9.16.1-Ubuntu <<>> jellyfin.ar
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48400
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;jellyfin.ar.			IN	A

;; ANSWER SECTION:
jellyfin.ar.		0	IN	A	10.1.0.7

;; Query time: 3 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Jul 20 17:42:20 -03 2022
;; MSG SIZE  rcvd: 56

If I tested on a public DNS I’m not going to find it, because it’s a local domain (there is no “Aswer Section”):

$ dig @1.1.1.1 jellyfin.ar

; <<>> DiG 9.16.1-Ubuntu <<>> @1.1.1.1 jellyfin.ar
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 49909
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;jellyfin.ar.			IN	A

;; AUTHORITY SECTION:
ar.			86400	IN	SOA	c.dns.ar. noc.nic.gob.ar. 2022072039 43200 3600 1728000 86400

;; Query time: 435 msec
;; SERVER: 1.1.1.1#53(1.1.1.1)
;; WHEN: Wed Jul 20 17:48:20 -03 2022
;; MSG SIZE  rcvd: 94

Here you can find how I use dig to test my pi-hole DNS I use with Docker, also how to set up WireGuard as your VPN:

https://blog.matiasmercado.ar/archives/71

ethtool

This command is used to control and query network device drivers and hardware settings. With this command, we can know about our network information card (NIC now on).

Some systems don’t come with ethtool, so to install ethtool just type:

$ sudo apt install ethtool

The initial syntax of ethtool for getting information about a NIC:

$ ethtool "interface"

Use ifconfig to check the name of the interface:

$ ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:50ff:feab:41a8  prefixlen 64  scopeid 0x20<link>
        ether 02:42:50:ab:41:a8  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 332  bytes 61597 (61.5 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eno2: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.1.0.24  netmask 255.255.255.0  broadcast 10.0.0.255
        inet6 fec0::2c2d:9e68:fb85:c0a8  prefixlen 64  scopeid 0x20<link>
        ether 04:92:26:d9:f4:29  txqueuelen 1000  (Ethernet)
        RX packets 488169  bytes 448776919 (448.7 MB)
        RX errors 0  dropped 533  overruns 0  frame 0
        TX packets 152619  bytes 28845661 (28.8 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
        device interrupt 16  memory 0xa3200000-a3220000  

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 16554  bytes 1579150 (1.5 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 16554  bytes 1579150 (1.5 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Then ethtool on eno2:

$ sudo ethtool eno2
[sudo] password for matiasm: 
Settings for eno2:
	Supported ports: [ TP ]
	Supported link modes:   10baseT/Half 10baseT/Full
	                        100baseT/Half 100baseT/Full
	                        1000baseT/Full
	Supported pause frame use: No
	Supports auto-negotiation: Yes
	Supported FEC modes: Not reported
	Advertised link modes:  10baseT/Half 10baseT/Full
	                        100baseT/Half 100baseT/Full
	                        1000baseT/Full
	Advertised pause frame use: No
	Advertised auto-negotiation: Yes
	Advertised FEC modes: Not reported
	Speed: 1000Mb/s
	Duplex: Full
	Auto-negotiation: on
	Port: Twisted Pair
	PHYAD: 1
	Transceiver: internal
	MDI-X: on (auto)
	Supports Wake-on: pumbg
	Wake-on: g
        Current message level: 0x00000007 (7)
                               drv probe link
	Link detected: yes

In the last line “Link detected: yes” is telling us that the interface is working. Also, we can see that the speed setting is 1000 Mb/s, full duplex and the auto-negotiation is on.

Now let’s see the drivers of this NIC:

$ sudo ethtool -i eno2
driver: e1000e
version: 5.18.10-76051810-generic
firmware-version: 0.5-4
expansion-rom-version: 
bus-info: 0000:00:1f.6
supports-statistics: yes
supports-test: yes
supports-eeprom-access: yes
supports-register-dump: yes
supports-priv-flags: yes

Let’s get some stats:

$ sudo ethtool -S eno2 | column
NIC statistics:				     tx_single_coll_ok: 0
     rx_packets: 542245			     tx_multi_coll_ok: 0
     tx_packets: 168386			     tx_timeout_count: 0
     rx_bytes: 510770337		     tx_restart_queue: 0
     tx_bytes: 31602892			     rx_long_length_errors: 0
     rx_broadcast: 119052		     rx_short_length_errors: 0
     tx_broadcast: 199			     rx_align_errors: 0
     rx_multicast: 9640			     tx_tcp_seg_good: 3553
     tx_multicast: 2550			     tx_tcp_seg_failed: 0
     rx_errors: 0			     rx_flow_control_xon: 0
     tx_errors: 0			     rx_flow_control_xoff: 0
     tx_dropped: 0			     tx_flow_control_xon: 0
     multicast: 9640			     tx_flow_control_xoff: 0
     collisions: 0			     rx_csum_offload_good: 426170
     rx_length_errors: 0		     rx_csum_offload_errors: 0
     rx_over_errors: 0			     rx_header_split: 0
     rx_crc_errors: 0			     alloc_rx_buff_failed: 0
     rx_frame_errors: 0			     tx_smbus: 0
     rx_no_buffer_count: 0		     rx_smbus: 0
     rx_missed_errors: 0		     dropped_smbus: 0
     tx_aborted_errors: 0		     rx_dma_failed: 0
     tx_carrier_errors: 0		     tx_dma_failed: 0
     tx_fifo_errors: 0			     rx_hwtstamp_cleared: 0
     tx_heartbeat_errors: 0		     uncorr_ecc_errors: 0
     tx_window_errors: 0		     corr_ecc_errors: 0
     tx_abort_late_coll: 0		     tx_hwtstamp_timeouts: 0
     tx_deferred_ok: 0			     tx_hwtstamp_skipped: 0

Let’s test this interface (this command runs for a few second). We can test it in two ways:

  • Offline (default): tests register, memory, loopback, interrupt.
  • Online (online arg): tests nvram and link
$ sudo ethtool -t eno2
The test result is PASS
The test extra info:
Register test  (offline)	 0
Eeprom test    (offline)	 0
Interrupt test (offline)	 0
Loopback test  (offline)	 0
Link test   (on/offline)	 0
$ sudo ethtool -t eno2 online
The test result is PASS
The test extra info: 
nvram test     (online)          0 
link test      (online)          0 
Register test  (offline)	 0
Eeprom test    (offline)	 0
Interrupt test (offline)	 0
Loopback test  (offline)	 0
Link test   (on/offline)	 0

We can change the NIC setting with ethtool. The syntax is easy, in the next example you can see how to set it full duplex, auto-neg on, 1000 Mb/s, and Wake-On-Lan on:

$ sudo ethtool -s eno2 speed 1000 duplex full autoneg on wol g

This is a very useful one, you can make the physical port of your NIC blink. Imagine you have a server with four ethernet adapters and you need to identify one of them:

$ sudo ethtool -p eno2

hostname

Using this command we can set the hostname. But it will not be permanent, when you reboot your system it will be back to his old name.

$ sudo hostname "name"

If you need to make a permanent change in the hostname, you will need to edit:

  • /etc/sysconfig/network on RHEL
  • /etc/hostname on Ubuntu/Debian
  • /etc/hosts on CentOS

ifconfig & iwconfig

In some new installations (and almost every docker container), this command isn’t installed. So in Debian/Ubuntu we need to install it:

$ sudo apt install net-tools

This is one of the most basic commands used to inspect our network. This command show us the name of the interface, the ipv4 and ipv6 address with netmask and broadcast, also the MTU and MAC adress of this interface. We can also see the loopback interface.

$ ifconfig
enp5s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.23.138.94  netmask 255.255.255.0  broadcast 172.23.138.255
        inet6 fe80::36a0:b51f:fe8f:b62a  prefixlen 64  scopeid 0x20<link>
        ether 34:40:b5:8f:a4:2a  txqueuelen 1000  (Ethernet)
        RX packets 2027103  bytes 775158667 (75.1 MB)
        RX errors 0  dropped 5944  overruns 0  frame 0
        TX packets 177462  bytes 39083952 (39.0 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
        device interrupt 18  memory 0xc1980000-c19a0000

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 316  bytes 28278 (28.2 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 316  bytes 28278 (28.2 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

The IP, mask and broadcast we can have the direction of the interface. The MTU, or maximum transmission unit, is the size largest protocol data unit (PDU) that can be communicated in a single network layer transaction. Smaller MTU can reduce network delay, larger MTU is associated with reduced overhead. MAC address (Media Access Control) is the “physical” direction using for identified a single interface on the network, this is unique identifier for the NIC. We can quickly identify the MAC address because it’s made of 6 blocks of 2 hexadecimal characters.

Any traffic that a computer program sends on the loopback interface is addressed to the same computer. This is why the Internet Protocol specified the loopback network as 127.0.0.0/8 for ipv4 and ::1 for ipv6. We use it often when we want to test a server, and we type “localhost” on our web browser. In that case, we are sending our traffic to the same computer.

We can use ifconfig with arguments, like

$ ifconfig -s
Iface      MTU    RX-OK RX-ERR RX-DRP RX-OVR    TX-OK TX-ERR TX-DRP TX-OVR Flg
docker0   1500        0      0      0 0             0      0      0      0 BMU
enp11s0   1500  2041268      0   6051 0        178226      0      0      0 BMRU
enp5s0    1500   354837      0     72 0         25355      0      0      0 BMRU
lo       65536      316      0      0 0           316      0      0      0 LRU
vethc9c7  1500      685      0      0 0          1107      0      0      0 BMRU
vethd464  1500        0      0      0 0           441      0      0      0 BMRU

This display a short list of interfaces (similar to netstat -i).

It shows us not only the list of interfaces available, but also the interfaces down.

# ifconfig -a

It only shows the info in that particular interface.

$ ifconfig enp5s0

Using sudo we can disable an active network, to make it active again, we need to use “up”

$ sudo ifconfig enp5s0 down

Being superuser, we can also configure an interface address.

$ sudo ifconfig enp5s0 172.23.138.15 netmask 255.255.255.0 broadcast 172.23.138.255

With this we can change the MTU size, this is a value between 0 and 4294967295, if you are not sure if you need to change it, leave it default.

$ sudo ifconfig enp5s0 mtu 1500

Similar to ifconfig, iwconfig get us information for wireless networks

$ iwconfig
lo        no wireless extensions.

eno2      no wireless extensions.

wlo1      IEEE 802.11  ESSID:"Office-5GHz"  
          Mode:Managed  Frequency:5.18 GHz  Access Point: A8:F4:49:9B:F9:8E   
          Bit Rate=866.7 Mb/s   Tx-Power=17 dBm   
          Retry short limit:7   RTS thr:off   Fragment thr:off
          Power Management:on
          Link Quality=68/70  Signal level=-42 dBm  
          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
          Tx excessive retries:0  Invalid misc:52   Missed beacon:0

We can find the WiFi networks avaibles using:

$ sudo iwlist wlp3s0 scan | grep ESSID
                    ESSID:"Office-5GHz"
                    ESSID:"Home-Wifi"
                    ESSID:"Neighbour-5GHz"
                    ESSID:"Banana-Wifi"

Now to connect to a WiFi we need a new command: nmcli

$ nmcli d wifi connect Office-5GHz password theadminnotes

There’s also an interactive alternative to nmcli to join a wireless network: nmtui


mtr

This tool is a result of 2 other commands, ping & traceroute. We are going to send packages to a destination but instead of getting one result with his hops or getting multiples responses with an OK o TTL timeout, it continuously displays information. It’s used to check the network issues:

We can get a report on a file with the argument “-r“, also with “-c” we define a limited number of packages we send :

$ mtr -rc 5 google.com > mtrGoogle-report
$ cat mtrGoogle-report
Start: 2022-07-24T15:55:25-0300
HOST: pop-os                      Loss%   Snt   Last   Avg  Best  Wrst StDev
  1.|-- _gateway                   0.0%     5    0.5   0.5   0.5   0.6   0.1
  2.|-- 200.52.231.1               0.0%     5    3.0   8.9   3.0  17.3   5.9
  3.|-- 74.135.36.151              0.0%     5   19.0  20.6  19.0  25.8   2.9
  4.|-- 74.135.36.150              0.0%     5   19.1  19.5  19.0  20.8   0.8
  5.|-- 74.135.252.209             0.0%     5   21.1  21.1  21.0  21.3   0.1
  6.|-- 142.251.77.1               0.0%     5   21.6  21.5  21.3  21.8   0.2
  7.|-- eze10s01-in-f14.1e100.net  0.0%     5   20.0  19.9  19.7  20.0   0.1

Another arguments for mtr are:

# Watch IP address
$ mtr -n google.com

# If we need IP and domains
$ mtr -b google.com

# Set a maximum number of hops
$ mtr -m 10 google.com

ip

This command manage routing, network devices, interfaces and tunnels. Similar to ifconfig, we can use it to give us info about or interfaces and address:

$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group 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
       valid_lft forever preferred_lft forever
2: enp5s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP qlen 1000
    link/ether 34:40:b5:8f:a4:2a brd ff:ff:ff:ff:ff:ff
    inet 172.23.128.94/24 metric 100 brd 172.23.128.255 scope global dynamic enp5s0
       valid_lft 67509sec preferred_lft 67509sec
    inet6 fe80::3640:b5ff:fe8f:b42a/64 scope link
       valid_lft forever preferred_lft forever

The same info, displayed differently, so for this purpose you can use which command you remember first. You can also use “ip a“.

The syntax to show us a specific interface is:

$ ip a show enp5s0
2: enp5s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP qlen 1000
    link/ether 34:40:b5:8f:a4:2a brd ff:ff:ff:ff:ff:ff
    inet 172.23.128.94/24 metric 100 brd 172.23.128.255 scope global dynamic enp5s0
       valid_lft 67509sec preferred_lft 67509sec
    inet6 fe80::3640:b5ff:fe8f:b42a/64 scope link
       valid_lft forever preferred_lft forever

To check the routes (similar to route), you can use ip route:

$ ip route
default via 10.1.0.1 dev eno2 proto dhcp metric 100 
10.1.0.0/24 dev eno2 proto kernel scope link src 10.0.0.14 metric 100 
169.254.0.0/16 dev eno2 scope link metric 1000 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 

netplan

Netplan is a new utility that Ubuntu is using to configure their network systems. Netplan was first introduces in Ubuntu 17.10 and today is the principal tool to configure our network. This service works with a YAML file to be configured, also runs with NetworkManager and systemd-networkd network daemons.

We can find the configuration file on /etc/netplan, there we are going to find a YAML file name it like this:

00-installer-config.yaml

This is how it’s look like:

# Remember YAML files whitespaces and tabs defines start/end of fields

network:
 version: 2                           #Remember to define the version
  ethernets:
    enp0s25:                           #Interface
      dhcp4: no                        #DHCP (IPv4) or static in this case
      addresses:               
        - 10.1.0.20/24                 #IP, mask and gateway
      gateway4: 10.1.0.1
      nameservers:                     #DNS
        addresses: [1.1.1.1, 1.0.0.1]
  

After setting your interfaces as DHCP or static, you need to type to apply changes:

$ sudo netplan try
[sudo] password for matiasm: 
Do you want to keep these settings?


Press ENTER before the timeout to accept the new configuration

Changes will revert in 117 seconds

With try argument, we can test if the configuration was correct. Press enter if you want that setting. You can also skip this first test (but isn’t recommended) using:

$ sudo netplan apply

netstat & ss

Network statistics. netstat command provides statistical figures about different interfaces which include open sockets, routing tables and connection information. Like tcpdump, this command need to be filtered to get a more readable content, because it displays a lot of information. Look by yourself just typing:

$ netstat

You can observe in the output the display of all open sockets, ip, ports and more. So let start filtering like tcpdump:

# To display programns/services running
$ netstat -p

# Display information about protocols and port numbers 
$ netstat -s

# Why use s to ports and p to service? I dont know

# Display open ports
$ netstat -a

# Like route -n, to list kernel IP routing table
$ netstat -r

# Display statistics about interfaces
$ netstat -i

# Specific interface statistics
$ netstat -e eth0

The command ss, as ip neigh, come to replace netstat. Netstat come included in the net-tools package. This package is no longer actively developed, and most of those tools have been deprecated in favor of their ss equivalents.

This command, as netstat, gives information about all TCP, UDP and UNIX. We can filter with “-t” (tcp), “-u” (udp), “-x” (unix)

# Combining with "a" argument to show connected and listeing sockets
$ ss -ta
$ ss -ua
$ ss -xa

# Using "l" argument to display listening sockets
$ ss -tl
$ ss -ul
$ ss -xl

# List stablished socket of TCP on IPv4
$ ss -t4 state established

# List closed socket of TCP on IPv4
$ ss -t4 state closed

# Check TCP connection without domain resolution
$ ss -tn

# List connected ports to a specific IP address
$ ss dst 10.2.0.70

# Check process running with "p", in this example we filter by TCP 
# packets, listening sockets, p process running and with a state establish
$ ss -tlp state established

# To filter a port with a connection stablished, we need to filter by
# source port and destination port
$ sudo ss -t sport = :22
$ sudo ss -t dport = :80

ping

One of the most famous commands on our list, ping check the connectivity between two nodes. These commands send the ICMP echo request to check the network connectivity. It keeps executing until it’s interrupted. You can use Ctrl+C to stopped. We can use it with IP directions or with domains.

$ ping 1.1.1.1
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
64 bytes from 1.1.1.1: icmp_seq=1 ttl=58 time=52.2 ms
64 bytes from 1.1.1.1: icmp_seq=2 ttl=58 time=22.8 ms
64 bytes from 1.1.1.1: icmp_seq=3 ttl=58 time=22.7 ms
64 bytes from 1.1.1.1: icmp_seq=4 ttl=58 time=29.0 ms
^C
--- 1.1.1.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3005ms
rtt min/avg/max/mdev = 22.705/31.672/52.229/12.137 ms

You can see here 4 packs of 64 bytes received, with a delay of 52.2, 22.8, 22.7 and then 29.0 ms. Also, a little statistics, 4 send it, 4 received, 0% of packet loss and averages.

If we use the argument “-c” we can specify the number of package to be sent.

# $ ping -c "number" "destination"

$ ping -c 2 1.1.1.1
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
64 bytes from 1.1.1.1: icmp_seq=1 ttl=58 time=53.1 ms
64 bytes from 1.1.1.1: icmp_seq=2 ttl=58 time=22.8 ms

--- 1.1.1.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 22.783/37.951/53.119/15.168 ms

Another uses of ping are:

# -6 or -4 tells ping the IP protocol, v4 or v6
$ ping -6 "destination IPv6" 

# Fastest way to ping localhost
$ ping 0

# Change the time interval between package, the minimum is 0.2 (200 ms)
$ ping -i 0.5 www.google.com

# Change the packet size, with a maximum of 655507 (65515 bytes)
$ ping -s 1000 1.1.1.1

# Flood a network to test performance
$ sudo ping -f localhost

route

With this command, we can set/modify our routing table that exist in the server. To check our network routes:

$ route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         _gateway        0.0.0.0         UG    0      0        0 eno2
default         _gateway        0.0.0.0         UG    600    0        0 wlo1
10.1.0.0        0.0.0.0         255.255.255.0   U     0      0        0 eno2
10.1.0.0        0.0.0.0         255.255.255.0   U     600    0        0 wlo1
link-local      0.0.0.0         255.255.0.0     U     1000   0        0 eno2
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0

If we need to display the IP address:

$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.1.0.1        0.0.0.0         UG    0      0        0 eno2
0.0.0.0         10.1.0.1        0.0.0.0         UG    600    0        0 wlo1
10.1.0.0        0.0.0.0         255.255.255.0   U     0      0        0 eno2
10.1.0.0        0.0.0.0         255.255.255.0   U     600    0        0 wlo1
169.254.0.0     0.0.0.0         255.255.0.0     U     1000   0        0 eno2
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0

You can make a route to communicate 2 different networks, if we have a 10.1.0.0/24 and 10.2.0.0/24 connected to a gateway, we can type in the gateway(10.2.0.1):

$ route add -net 10.2.0.0 netmask 255.255.255.0 gw 10.2.0.1

Now, the packets addressed to 10.2.0.x network will be forwarded via the 10.2.0.1 interface. You need to do the same the other way, connecting with the interface gateway we are going to use on 10.1.0.0/24:

$ route add -net 10.1.0.0 netmask 255.255.255.0 gw 10.1.0.1

If we need to add a gateway (to allow internet access, for instance):

$ sudo route add default gw 172.23.128.1

You can block a route to a particular host:

$ sudo route add -host 10.3.0.70 reject

Or reject and entire network

$ route add -net 10.3.0.0 netmask 255.255.255.0 reject

ssh

I’m thinking to do a complete analysis of this command with different clients like PuTTY, mobaXterm, tilix and more, so stay tuned. The ssh command provides a secure encrypted connection between 2 hosts over an insecure network. This connection can also be used for terminal access, file transfers, and for tunneling to other applications. First you need to install it, because in some systems it comes as an optional service, in Debian base systems:

$ sudo apt install openssh-server

Check if it’s enabled:

$ sudo /etc/init.d/ssh status
● ssh.service - OpenBSD Secure Shell server
     Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled)
     Active: active (running) since Thu 2022-07-28 11:12:00 UTC; 5 days ago
       Docs: man:sshd(8)
             man:sshd_config(5)
   Main PID: 915 (sshd)
      Tasks: 1 (limit: 9394)
     Memory: 13.1M
        CPU: 934ms
     CGroup: /system.slice/ssh.service
             └─915 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups"

If it’s not running, use:

$ sudo /etc/init.d/ssh start

You can edit the config of ssh from /etc/ssh/sshd_config. I recommend you to change the default port to another you like (careful to not use another default port). This is a simple yet effective way to prevent attacks. The default port of ssh (22) it’s the most attacked to gain access to a server. If you changed, and of course, you change your password often, you can have a secure system. Remember to reload the service if you change the port:

$ nano /etc/ssh/sshd_config

# Search for the # Port option, and uncomment it

Port 2022

After that, you just need to open that port on your firewall:

# In case you don't change the port
$ sudo ufw allow ssh

# In case you change the port
$ sudo ufw allow "port number"

Now you can connect from another host in the same net. If your server was public, of course you can now access remotely:

# Use the follow format "user"@"domain/IP" -p "port" (without arguments use default port)

$ ssh [email protected] -p 2022

It’s going to ask for your password.

Connect your trusted computer directly using an ssh key.

First, create an ssh key:

$ ssh-keygen -b 2048 -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/matias/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/matiasm/.ssh/id_rsa
Your public key has been saved in /home/matiasm/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:SizPajsldfdmN4wiqhwelqy7Bd2CorQXxieDt6oTgYVBdlk matiasm@senalu-svr
The key's randomart image is:
+---[RSA 2048]----+
|   .+o.oEo o.o . |
|   ..oo ..O *.o .|
|    .o.. = B.o . |
|    .+..o oo.=.  |
|    + +.S-o *oo  |
|   . *.... ..=   |
|      =o    . .  |
|      o.         |
|       .         |
+----[SHA256]-----+

You can see that this generates a public and a private key, we are going to copy the public on the server and save the private for ourselves, do not share this private key!. These keys are stored in .ssh. Copy the public key:

$ cat .ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAajshdasdB6NArwF59HYrr5J8veh1tkPRlrX59CHzhwiGZGpLU633QztdGzs8YOunSVrgUpAIe1s9B5t/Bh2my3OzwSPK/7570lB+1eevTO5DO6qtiTVJDFo/NCINQqgG8+XZV+WpnViwABuBtVb0c3+Vfclr5AJASudnaDIdoOLvMCYvoM844ejpUNYgPBdJXpy4r/gI9QZZ48xmR0/a0totaiWpBwCIF2623123jvR8G0IGzq3z9tyttgW304rr3kYp4UJpy+4EgbZtbQnjRTrPhMrPboKA5bxCB1n4Z3zTyctTlBjcPrJknL+wEhLQJbrgVIhG51cQ5gZac9yoa4C7 matias@server

Paste this key on the server on:

$ sudo nano .ssh/authorized_keys

Now try connecting to the server, it should not ask you for a password.


tcpdump

The tcpdump command capture traffic that is passing through the network interface. This is one of the most used commands to resolve issues in our network.

We can start checking what happen on our interface using:

$ sudo tcpdump -i eno2

We can see a lot of information displayed that show us what happens in our interface. This information displayed this way is useless, so we are going to need to filter it to make it readable, so here you have a list of arguments to filter this information:

# To get only tcp/udp packets
$ sudo tcpdump -i eno2 tcp

# To get traffic only from a specific port 
$ sudo tcpdump -i eno2 port 80

# To get traffic only from a specific range of ports 
$ sudo tcpdump -i eno2 portrange 20 23 

# Get only a number of packets captured (if not, you need to stop it mannually)
$ sudo tcpdump -i eno2 -c 20

# Get only a specific subnet
$ sudo tcpdump -i net 10.2.0.0/24

We can get a report of the traffic if we move the result to a file

$ sudo tcpdump -i eno2 -c 100 > tcpdump-report

# You can also use
$ sudo tcpdump -i eno2 -c 100 -w tcpdump-report

If you want to capture all the networks on your system/server:

$ sudo tcpdump -i any

traceroute & tracepath

The command traceroute is used to troubleshooting the network. We can see that traceroute make us a numbered list with every step a network package make to his way to the destination. This means that we get a list with the domains/IP of every router or server the package arrive at his way. Remember that traceroute doesn’t come installed, you have to install the package name it “traceroute” or “inetutils-traceroute”

$ traceroute google.com
traceroute to google.com (142.251.133.238), 30 hops max, 60 byte packets
 1  _gateway (10.1.0.1)  1.037 ms  1.684 ms  2.337 ms
 2  200.51.226.1 (200.51.226.1)  15.712 ms  15.796 ms  15.835 ms
 3  72.14.238.91 (72.14.238.91)  36.750 ms 74.125.32.151 (74.125.32.151)  32.262 ms 72.14.238.91 (72.14.238.91)  37.388 ms
 4  72.14.208.90 (72.14.208.90)  36.891 ms 74.125.51.138 (74.125.51.138)  36.929 ms  37.006 ms
 5  74.125.242.209 (74.125.242.209)  33.642 ms  36.679 ms  33.701 ms
 6  142.251.239.157 (142.251.239.157)  37.266 ms 142.251.239.160 (142.251.239.160)  24.938 ms 142.251.77.0 (142.251.77.0)  41.273 ms
 7  142.251.239.155 (142.251.239.155)  40.839 ms  40.892 ms 172.253.53.18 (172.253.53.18)  40.966 ms
 8  eze10s08-in-f14.1e100.net (142.251.133.238)  40.173 ms  40.095 ms  40.238 ms

Here you can see the easy that is to watch every step of the package travel, it is very useful to know how the route is made and if in some step there is a delay. We can see after this command we get the maximum number of hops that the package need to get a response from the server, also de IP and package size.

For the fastest traceroute, you can use the argument-n that do not try to map IP address to host names, this avoids DNS lookup :

$ traceroute -n google.com
traceroute to google.com (216.58.202.110), 30 hops max, 60 byte packets
 1  10.1.0.1  0.946 ms  1.625 ms  2.289 ms
 2  200.51.231.1  37.374 ms  41.304 ms  41.344 ms
 3  72.14.228.91  41.661 ms 74.125.32.151  41.980 ms  42.109 ms
 4  74.125.52.126  41.752 ms 74.125.32.150  33.270 ms  33.194 ms
 5  * * *
 6  209.85.250.153  37.139 ms  36.501 ms  34.156 ms
 7  216.58.202.110  39.131 ms  24.293 ms  26.820 ms

The tracepath command work very similar to traceroute, but this is dedicated to check delays in every hop.

$ tracepath blog.matiasmercado.ar
 1?: [LOCALHOST]                      pmtu 1480
 1:  _gateway                                              1.350ms 
 1:  _gateway                                              1.161ms 
 2:  _gateway                                              1.058ms pmtu 1480
 2:  ???                                                   3.579ms 
 3:  ???                                                  22.595ms asymm  4 
 4:  ???                                                  22.565ms asymm  5 
 5:  190.212.118.147                                      22.711ms asymm  7 
 6:  customer-static-210-120-169.iplannetworks.net        23.933ms 
 7:  smtp249.allytech.com                                 23.378ms 
 8:  no reply

With the “-b” argument, we get the IP address next to the domain. With “-p” argument, we can select the port we are going to use:

$ tracepath -bp 8080 blog.matiasmercado.ar
1?: [LOCALHOST]                      pmtu 1480
 1:  _gateway (10.1.0.1)                                   1.173ms 
 1:  _gateway (10.1.0.1)                                   1.141ms 
 2:  ??? (200.52.251.1)                                    3.795ms 
 3:  ??? (200.51.245.57)                                  19.713ms asymm  4 
 4:  ??? (200.53.235.58)                                  22.564ms asymm  5 
 5:  190.210.118.157 (190.210.118.157)                    32.583ms asymm  7 
 6:  customer-static-210-110-149.iplannetworks.net (190.210.110.149)  23.929ms 
 7:  smtp249.allytech.com (200.68.105.249)                22.090ms 
 8:  no reply


whois

The command whois is a query that get a response with information about the domain, owner, admin, registry, last update and more. This information is regulated by the office in charge of the domain of each country, so the information displayed could change depends on where it is hosted.

$ whois ole.com.ar
% La información a la que estás accediendo se provee exclusivamente para
% fines relacionados con operaciones sobre nombres de dominios y DNS,
% quedando absolutamente prohibido su uso para otros fines.
%
% La DIRECCIÓN NACIONAL DEL REGISTRO DE DOMINIOS DE INTERNET es depositaria
% de la información que los usuarios declaran con la sola finalidad de
% registrar nombres de dominio en ‘.ar’, para ser publicada en el sitio web
% de NIC Argentina.
%
% La información personal que consta en la base de datos generada a partir
% del sistema de registro de nombres de dominios se encuentra amparada por
% la Ley N° 25326 “Protección de Datos Personales” y el Decreto
% Reglamentario 1558/01.

domain:		ole.com.ar
registrant:	30500124152
registrar:	nicar
registered:	1996-01-01 00:00:00
changed:	2021-12-21 18:39:35.105665
expire:		2023-01-01 00:00:00

contact:	30500124152
name:		ARTE GRAFICO EDITORIAL ARGENTINO S A
registrar:	nicar
created:	2013-08-22 00:00:00
changed:	2022-05-10 15:23:25.610917

nserver:	cash.ns.cloudflare.com ()
nserver:	vita.ns.cloudflare.com ()
registrar:	nicar
created:	2016-07-01 00:30:07.155852

ole.com.ar it’s an Argentinian website with information about sports. We can see here the domain, registrant, when it was registered for the first time, last change, name of the business and nameserver that hosted.


I hope this post get into your bookmark, I think this covert more than a basics of networking with Linux. If you have any doubt or correction to make, please feel free to comment, you don’t need any registration to comment.

1 thought on “Networking with Linux: commands, services and more”

Leave a Comment

Your email address will not be published. Required fields are marked *