The Linux command line is where visibility, control, and power meet — and nowhere is that more true than in security work.
The 11 commands discussed in this post are staples for administrators, penetration testers, and defenders alike. They let you discover devices on a network, inspect traffic, test authentication, and hunt for rootkits, all from a terminal. Because these tools operate at a low level and can be disruptive if misused, this guide focuses on practical usage, realistic examples, and defensive context so you can apply them responsibly to harden systems, investigate incidents, or learn offensive techniques in a safe, legal environment.
arp from the net-tools package helps to manage the cache for the address resolution protocol (ARP). This cache contains a list of local network devices and allows the assignment to their MAC addresses. Without any further parameters, the command returns the current cache content. With the -n option, the corresponding IP addresses are displayed instead of host names.
user$ arp
Address HWtype HWaddress Flags Mask Iface
fritz.box ether 3c:37:12:b7:a1:cb C enp0s1
Archer-C6.fritz.box ether d8:07:b6:4f:19:af C enp0s1
m3.fritz.box ether 80:a9:97:32:c5:d7 C enp0s1
BRN001BA99C5DA4.fritz.b ether 00:1b:a9:9c:5d:a4 C enp0s1
192.168.178.1 ether 3c:37:12:b7:a1:cb C enp0s1
192.168.178.21 ether d8:07:b6:4f:19:af C enp0s1
192.168.178.146 ether 80:a9:97:32:c5:d7 C enp0s1
192.168.178.20 ether 00:1b:a9:9c:5d:a4 C enp0s1
arp-scan sends address resolution protocol (ARP) packets to the specified hosts or IP addresses and displays the resulting responses. arp-scan thus provides an extremely fast way of finding out which hosts or IP addresses are running active devices and which MAC addresses they have. As usual, the address range can also be specified in the form 10.17.0.0/16.
The nmap command provides similar functions, albeit on a completely different technical basis. In short, nmap is slower but more thorough.
Example: The following arp-scan command is used to perform a network scan for the IP addresses 10.0.0.*:
root# arp-scan --interface=enp0s3 10.0.0.0/24
Interface: enp0s3, datalink type: EN10MB (Ethernet)
Starting arp-scan 1.9 with 256 hosts
10.0.0.9 00:16:b6:9d:ff:4b Cisco-Linksys
10.0.0.22 b8:27:eb:11:44:2e Raspberry Pi Foundation
10.0.0.39 ac:87:a3:1e:4a:87 (Unknown)
...
7 packets received by filter, 0 packets dropped by kernel
Ending arp-scan 1.9: 256 hosts scanned in 1.825 seconds
(140.27 hosts/sec). 7 responded
The chkrootkit command from the package of the same name searches the system for known rootkits. The procedure is pretty simple: the command attempts to detect the malware by using simple criteria or signatures (e.g., the presence of certain character strings in binary files).
Although the project is still active, further development is only taking place in small steps. Both false positives and the failure to detect genuine threats are possible.
Example
root# chkrootkit
ROOTDIR is /
Checking amd... not found
Checking basename... not infected
Checking biff... not found
Checking chfn... not infected
Searching for sniffer's logs ... nothing found
Searching for rootkit HiDrootkit's files... nothing found
Searching for rootkit t0rn's default files... nothing found
Checking asp... not infected
Checking bindshell... not infected
Checking lkm... chkproc: nothing detected
...
Variants: chkrootkit can be the starting point of a rootkit search due to its ease of use. Alternative or supplementary tools are, for example, rkhunter and the commercial tools Lynis and Snort. The latter two programs each have an open-source kernel that can be used free of charge.
Fail2ban is a security program that monitors logins and blocks the IP address in question for a certain period of time after repeated incorrect logins. If Fail2ban has been set up, its function can be checked and changed via fail2ban-client.
If fail2ban-client is executed without commands only with the -d option, the command outputs the entire currently valid configuration, whereby only the filters, jails, and actions that are actually in use are taken into account. This is very helpful in troubleshooting due to the confusing configuration files.
Examples: The following commands show that four jails are active on the test computer. The jail for the SSH server has already temporarily blocked 1,418 IP addresses in the past. Currently, 3 addresses are blocked.
root# fail2ban-client status
Status
Number of jail: 4
Jail list: dovecot, postfix, sshd, sshd-ddos
root# fail2ban-client status sshd
Status for the jail: sshd
Filter
Currently failed: 4
Total failed: 151362
Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd
Actions
Currently banned: 3
Total banned: 1418
Banned IP list: 58.218.nnn.nnn 58.242.nnn.nnn 180.76.nnn.nnn
You can unblock an erroneously blocked IP address using fail2ban-client set (here, we do this for the SSH jail):
root# fail2ban-client set sshd unbanip 1.2.3.4
The hacking or penetration testing command hydra from the package of the same name reads passwords from a file or generates them itself and attempts to use them to log in to a network service.
hydra supports a wide range of services, including FTP, HTTP(S), IMAP, MySQL, Microsoft SQL, POP3, PostgreSQL, SMTP, Telnet, and VNC. The command can also attempt logins in web forms (GET, PUT, POST). You can determine the list of permitted service names using hydra -h.
Example: With -x '4:6:aA1-_$%', hydra uses passwords that are four to six characters long and contain the characters -, _, $, and % in addition to letters and numbers. With -x '4:4:1', hydra tries all four-digit numbers. This results in 10,000 possibilities.
The -x option is only useful in exceptional cases, namely if you have (almost) an infinite amount of time and the target computer tolerates an unlimited number of login attempts.
Example: In the following example, hydra tries to find an account on a Linux server with a trivial password or no password at all for an SSH login. To do this, cut first generates a list of all accounts. Ideally, you should run this command on a computer running the same distribution as the target computer.
user$ cut -d: -f1 /etc/passwd > logins.txt
After that, hydra is supposed to try an SSH login for all accounts stored in logins.txt, using the account name, the reversed account name, and an empty character string as the password:
user$ hydra -L logins.txt -t 4 -e nsr 10.0.0.36 targethost
Alternatives: If you know passwords in the form of hash codes, you can try to find out the plain-text passwords with the offline password cracker (see john). hashcat is even faster. However, this command requires the sometimes-complicated installation of suitable GPU drivers.
The program John the Ripper (command and package name john) is an offline password cracker. To use the program, you must have the passwords as hash codes. john then tests whether self-generated passwords or passwords from a predefined list correspond to the hash codes.
john can handle most common hash algorithms. In the simplest case, you simply pass the name of a text file containing hash codes line by line to the command. The lines of the text file can also have the following format: name:hashcode:xxx. john first tries the account name as password (if available), then passwords from a built-in word list, and finally passwords that it generates itself (--single, --wordlist, and --incremental mode). Cracked passwords are stored in .john/john.pot.
Specifies which hash method john should use. The command supports the following formats, among others: afs, bcrypt, bsdicrypt, crypt, descrypt, dummy, lm md5crypt, and tripcode. This option is only required if john doesn’t recognize the hash method itself.
A brief description of the hash formats can be found on this website. Note that this website also describes formats that are only included in the unofficial “jumbo” version (see the “Alternatives” section).
Generates passwords itself, first trying out short and then increasingly longer passwords. Note that, in this mode, john runs endlessly, unless the passwords you’re looking for are trivial.
By default, the characters a–z, A–Z, and 0–9 are taken into account in this mode (corresponds to alnum, 62 characters). Optionally, you can restrict the character set: lower corresponds to a–z, lowernum includes a–z and 0–9, alpha corresponds to a–z and A–Z, and digits includes digits only. Some other modes that can be defined are provided in /etc/john/john.conf. (On Ubuntu, many modes don’t work because the corresponding character set files are missing in /usr/share/john.)
Finally, you can use john --make-charset to generate your own character set file, which you can then use with --incremental=charsetfile. This website provides some useful tips on this.
Continues the execution of john that was interrupted by (Ctrl)+(C).
Displays passwords that have already been cracked. For this purpose, the .john/john.pot file gets evaluated.
Tries out the passwords contained in the file line by line.
Example: The starting point for this example is a Linux computer with multiple accounts. The unshadow command supplied with john combines /etc/passwd and /etc/shadow into a new hashes file. (The access to the shadow file requires root permissions.) The hash codes in the resulting file are abbreviated here for reasons of space:
root# unshadow /etc/passwd /etc/shadow > hashes
root# chown user hashes
user$ cat hashes
...
peter:$6$U.zGFBlF$LdNTE...:1001:1001::/home/peter:/bin/bash
maria:$6$gSJg6.d8$mN.en...:1002:1002::/home/maria:/bin/bash
hugh:$6$UinuQqJY$iD59.N...:1003:1003::/home/hugh:/bin/bash
john finds two particularly insecure passwords within seconds. peter has used his own name as his password, and hugh used the popular password “123456”. However, Maria’s password can’t be cracked straight away, which is why the process gets stopped after a while by pressing (Ctrl)+(C):
user$ john hashes
Loaded 3 password hashes with 3 different salts
Press 'q' or Ctrl-C to abort, almost any other key for status
peter (peter)
123456 (hugh)
<Strg>+<C>
You can download lists of popular passwords from GitHub using git. (Note that the space required for the lists is around 750 MiB!) One of these dictionaries actually contains Maria’s password! It reads secret:
user$ git clone https://github.com/danielmiessler/SecLists.git
user$ john --wordlist=SecLists/Passwords/Common-Credentials/ \
10-million-password-list-top-10000.txt hashes
Loaded 3 password hashes with 3 different salts
Remaining 1 password hash with 1 different salt
secret (maria)
Alternatives: On GitHub there is the greatly expanded, community-maintained “jumbo” version of john.
If you want to significantly speed up the cracking of hash codes with GPU support, you should consider using hashcat. The biggest hurdle in this case is the installation of suitable GPU drivers. To check network services for insecure passwords, you can use the online password cracker: hydra.
The nc command is better known as Netcat. It redirects TCP/UDP ports to standard input/output and provides a number of other functions. You can use the command to interactively test network protocols such as HTTP or SMTP in a way similar to telnet. With nc, you can also copy files via any network port, implement a chat, or set up a simple backdoor that receives and executes commands via a port. It’s therefore not surprising that nc is extremely popular among hackers and penetration testers.
On some Linux distributions, the nc command is included in the package of the same name; on other distributions, you must install netcat. Note that there are different implementations of Netcat. For example, netcat-traditional is used on Debian and Ubuntu, while RHEL provides a variant from the nmap developers (https://nmap.org/ncat). In practice, this doesn’t result in any major differences, but individual options may be implemented differently (or not at all) depending on the version.
A number of other options are described in man nc. A possible alternative to nc is the socat command, which isn’t covered in this book. It also supports the SCTP, can work via proxy servers, operate serial interfaces, and encrypt the data for transmission:
Examples: To copy a file via any port (here, 1234) from host 1 to host 2, you first start the receiver on host 2 (right column) and then initiate the transfer of the file to host 1 (left column):
host2$ nc -l 1234 > file
host1$ nc host2 1234 < file
It’s just as easy to conduct a chat. All you have to do is agree on a port with the other party. The chat is initiated on a computer via nc -l (left column). This way, nc monitors the specified port 1234 and waits for a connection to be established.
On the second host, nc is started without options to connect to the first host. There’s no visible confirmation that the connection has been established, but as soon as one of the two parties enters text (standard input) and confirms it by pressing (Enter), the text appears in the terminal of the other party (standard output).
host1$ nc -l 1234
host2$ nc host1 1234
how are you?
how are you?
good
good
<Ctrl>+<C>
The third example shows the potential danger of Netcat: Here, nc on host 1 is set up to pass all input received on port 1234 to the bash shell. Their outputs are transferred back to the transmitter. Shell commands can now be run on host 1 from a second host. Ls therefore shows files that are located on host 1!
host1$ nc -l 1234 -e /bin/bash
host2$ nc host1 1234
ls
file1
file2
file3
However, the -e option for executing a command isn’t available with all Netcat versions. It’s especially missing in the netcat-traditional implementation that’s common on Debian and Ubuntu. A solution to that is to install the nmap package and run the ncat command included there.
ngrep is referred to as a packet sniffer. The command reads the network traffic of a port and filters it. ngrep provides similar functions to the tcpdump command and, like this, uses the pcap library to read the network packets. Unlike tcpdump, however, ngrep also takes the contents of the packages into account. Naturally, this only works for nonencrypted protocols, such as HTTP or FTP.
The search expression must be formulated as a regular pattern as in grep. The syntax summarized in tcpdump applies to the pcap filter expression.
Example: The following example listens on all interfaces for HTTP packets containing the keywords user, pass, and so on:
root# ngrep -d any -i 'user|pass|pwd|mail|login' port 80
interface: any
filter: (ip or ip6) and ( port 80 )
match: user|pass|pwd|mail|login
T 10.0.0.87:58480 -> 91.229.57.14:80 [AP] POST /index.php
HTTP/1.1..Host: ... user=name&pass=geheim&login=Login
...
The nmap command (network mapper) from the package of the same name performs a port scan and attempts to determine which network services are active on the specified computer or in the specified network. nmap should only be used to analyze your own computers or after consultation with the respective administrator. A port scan of other computers can be interpreted as an attempted attack!
You must choose an -s option when calling. Only -sU may be combined with other -s options. In general, the right choice of options is a trade-off between thoroughness and speed.
In many cases, nmap -v -A name is sufficient to get an initial overview of the network services of the specified computer. Advanced nmap users can find more details on the man page and on the following websites:
Graphical user interfaces also exist for nmap, such as nmap-frontend or zenmap.
Examples: The following command performs a quick network scan on the local network (256 IP addresses). Thanks to the focus on the most important 100 ports, the job is done within about two seconds. The nmap outputs have been shortened for reasons of space and only show the results of two of the devices found:
root# nmap -F -T4 10.0.0.0/24
Nmap scan report for imac (10.0.0.2)
Host is up (0.00019s latency).
PORT STATE SERVICE
22/tcp open ssh
88/tcp open kerberos-sec
445/tcp open microsoft-ds
548/tcp open afp
MAC Address: AC:87:A3:1E:4A:87 (Apple)
Nmap scan report for raspberrypi (10.0.0.22)
Host is up (0.00038s latency).
Not shown: 99 closed ports
PORT STATE SERVICE
22/tcp open ssh
MAC Address: B8:27:EB:11:44:2E (Raspberry Pi Foundation)
...
Nmap done: 256 IP addresses (6 hosts up) scanned in 2.42 seconds
The second example shows the nmap result for a NAS device that is located in a different local network (again, it has been heavily shortened):
root# nmap -v -A 192.168.178.28
Nmap scan report for DiskStation.fritz.box (192.168.178.28)
Host is up (0.0023s latency).
...
Discovered open port 445/tcp on 192.168.178.28
Discovered open port 139/tcp on 192.168.178.28
Discovered open port 80/tcp on 192.168.178.28
Discovered open port 443/tcp on 192.168.178.28
Discovered open port 22/tcp on 192.168.178.28
Discovered open port 5001/tcp on 192.168.178.28
Discovered open port 5000/tcp on 192.168.178.28
Discovered open port 548/tcp on 192.168.178.28
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.4 (protocol 2.0)
ssh-hostkey:
2048 5a:e7:3a:66:f4:99:9f:0a:0a:... (RSA)
256 06:1a:bf:9f:e9:d0:64:3a:92:49:... (ECDSA)
256 ad:b7:7d:ab:ae:70:0a:c9:a6:0c:... (ED25519)
...
80/tcp open http nginx
139/tcp open netbios-ssn Samba smbd 4.6.2
445/tcp open netbios-ssn Samba smbd 4.6.2
...
Nmap done: 1 IP address (1 host up) scanned in 64.19 seconds
The rkhunter shell script (Rootkit Hunter) attempts to detect rootkits installed on the computer. Compared to chkrootkit, rkhunter performs even more tests. As is the case with chkrootkit, however, the program isn’t infallible: you must expect both false positives and that the program won’t detect a modern rootkit at all.
In some distributions, a cron script gets set up when the rkhunter package is installed, which calls rkhunter once a day and sends an email with the results. On Debian and Ubuntu, this feature is also provided, but it’s disabled in the /etc/default/rkhunter configuration file.
Example: The shortened version of the program reads as follows:
root# rkhunter –check
[ Rootkit Hunter version 1.4.6 ]
Checking system commands
...
Performing file properties checks
Checking for prerequisites [ OK ]
/usr/sbin/adduser [ OK ]
/usr/sbin/chroot [ OK ]
...
Performing check of known rootkit files and directories
55808 Trojan - Variant A [ Not found ]
ADM Worm [ Not found ]
AjaKit Rootkit [ Not found ]
...
Performing system configuration file checks
Checking for an SSH configuration file [ Found ]
Checking if SSH root access is allowed [ Warning ]
Checking if SSH protocol v1 is allowed [ Not allowed ]
System checks summary:
File properties checks: Files checked: 151, Suspect files: 1
Rootkit checks: Rootkits checked: 475, Possible rootkits: 0
...
All results have been written to the log file: /var/log/rkhunter.log
tcpdump from the package of the same name reads the network traffic of an interface, filters it according to criteria, outputs it, or saves it in a file. The command not only handles TCP packets, but also UDP and ICMP packets. tcpdump uses the pcap library internally to read and filter the network packets.
Filter Expression: The options can be followed by a filter expression, which can be composed of the following keywords, among others:
The host, net, and port keywords can optionally be prefixed with dst or src if the specification refers only to the packet destination or source.
You can link multiple filter conditions via and or dust. You must bracket complex expressions using \( and \). Alternatively, you can use simple parentheses, but then you have to put the entire filter expression in apostrophes (e.g., '(port 1 or port 2)'). Other filter options are described in man pcap-filter.
Examples: The following command outputs information about all HTTP packets flowing through the wlan0 interface:
root# tcpdump -i wlan0 port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on wlan0, link-type EN10MB (Ethernet)
10:34:33.681218 IP imac.57402 > bpf.tcpdump.org.http:
Flags [S], seq 755525464, win 65535, options [mss 1460,nop,wscale 5,nop,nop,
TS val 595975353 ecr 0,sackOK,eol], length 0 10:34:33.681793 IP imac.57403 >
bpf.tcpdump.org.http:
Flags [S], seq 2954861158, win 65535, ...
The second command records the next 100 HTTP packets flowing from or to the IP address 192.139.46.66 in the dump.pcap file:
root# tcpdump -i wlan0 -n -c 100 -w dump.pcap port 80 and host 192.139.46.66
The third example determines packets that flow through the bridge br0 and that contain the specified MAC address (as sender or target):
root# tcpdump -i br0 -en | grep -i '00:50:56:00:D0:56'
Mastering these Linux commands gives you a compact, practical toolkit for network discovery, traffic analysis, password auditing, and basic host forensics. Remember: tools are neutral and their value depends on how you use them. Always test on systems you own or where you have explicit permission, validate findings (many scans return false positives), and combine command-line checks with logs, up-to-date signatures, and layered defenses. Use virtual labs or isolated networks to practice, keep your toolset and signatures current, and treat every discovery as a prompt to improve configuration and monitoring rather than an end in itself.
Editor’s note: This post has been adapted from a section of the book Linux Command Reference: Shell Commands from A to Z by Michael Kofler. Dr. Kofler is a programmer and Linux administrator. He studied electrical engineering/telematics at Graz University of Technology. He has been one of the most successful and versatile computing authors in the German-speaking world for many years. His current topics include Linux, Docker, Git, hacking and security, Raspberry Pi, and the programming languages Swift, Java, Python, and Kotlin. Dr. Kofler also teaches at the Joanneum University of Applied Sciences in Kapfenberg, Austria.
This post was originally published 11/2025.