Overview
In this tutorial, learn to review security on your Linux system. Learn to:
- Audit a system to find files with the suid/sgid bit set.
- Set or change user passwords and password aging information.
- Use nmap and netstat to discover open ports on a system.
- Set up limits on user login events, processes, and memory usage.
- Determine which users have logged in to the system or are currently logged in.
- Use and configure sudo.
Basic security in Linux
Your Linux system requires protection from malicious outsiders and also abuse from legitimate users. Learn the basics of protecting your Linux system.
This tutorial helps you prepare for Objective 110.1 in Topic 110 of the Linux Administrator (LPIC-1) exam 101. The objective has a weight of 3. This tutorial reflects the Version 5.0 objectives as updated on October 29, 2018.
Prerequisites
To get the most from the tutorials in this series, you need a basic knowledge of Linux and a working Linux system on which you can practice the commands that are covered in this tutorial. You should also be familiar with material covered in our tutorials Learn Linux, 101: File and directory management,Learn Linux, 101: Manage file permissions and ownership, and Learn Linux, 101: Manage user and group accounts and related system files. Sometimes, different versions of a program format output differently, so your results might not always look exactly like the listings and figures that are shown here.
The examples in this tutorial come from Fedora 33, Slackware 14.2, and Ubuntu 20.04.1 LTS.
Find files with the suid/sgid bit set
Recall that the passwd
command saves your updated password in an encrypted form in /etc/shadow. If you look at the permissions on /etc/shadow, it has no permissions, meaning that only the owner (root) can read or update it. You probably wouldn’t want other people to read even an encrypted password, let alone change it. So, this behavior is reasonable. How does the passwd
command manage to update /etc/shadow? The answer is the suid
permission bit in the file attributes for the passwd
command. Listing 1 shows the file permissions on the three basic files related to passwords. I have used the stat
command to show both the usual and the octal file permissions. The more usual ls
command cannot display octal permissions. Make a note of the '%#
a formatting option to add a leading 0 to the octal permissions.
Listing 1. File permissions related to the passwd command
[ian@attic5-f33 ~]$ stat -c '%A %#a %U %G %n' /etc/shadow /etc/passwd /usr/bin/passwd
---------- 0 root root /etc/shadow
-rw-r--r-- 0644 root root /etc/passwd
-rwsr-xr-x 04755 root root /usr/bin/passwd
The -rwsr-xr-x
permission bits include ‘s’ in the user section, or equivalently 4000 in the octal form. This tells you that the program is run with permissions as if the root user had invoked it. That is how it is allowed to access /etc/shadow. Obviously any executable that can access any part of the file system with root authority is a potential security exposure. How many such files are there? Use the find
command with the -perm
option to locate files with specific permission bits set. Listing 2 shows how to find the total number of files with the suid bit set starting at the root of the file system. You will need to run this command with root authority. For this section of the tutorial, I use a terminal session with the root login environment on my Fedora 33 system. For many systems, particularly Debian-based systems such as Ubuntu, it is more normal to use these commands using the sudo
command. I will cover sudo
and its configuration later in this tutorial. If you are not already familiar with using sudo
, you can skip ahead to that section and then return here.
Listing 2. How many files have suid set?
[root@attic5-f33 ~]# find / -perm -4000|wc
find: ‘/run/user/1000/gvfs’: Permission denied
find: ‘/proc/49464/task/49464/fd/5’: No such file or directory
find: ‘/proc/49464/task/49464/fdinfo/5’: No such file or directory
find: ‘/proc/49464/fd/6’: No such file or directory
find: ‘/proc/49464/fdinfo/6’: No such file or directory
26 26 618
So I have 26 files on my system with the suid bit set. Not too many to check. Notice the specification of the permission bits to match as -4000
. The leading hyphen ‘-‘ tells find
to match any file that has all the specified bits set. If you want to look for files with multiple bits all set this is fine and in this case, there is only one bit to check. If you want to find files that have either suid or sgid bits set you should use the ‘/’ prefix, which matches any permission setting with at least one of the specified bits set.
There are several lines of output on stderr. If you are performing a security audit, you should at least review these to be sure that there are no surprises.
The find
command normally prints output to stdout. Use the -printf
option to format it, for example to include specific output fields. Use -fprintf
to print output to a file. Listing 3 shows how to generate a list of files in the file system with the suid bit set. I format the output to include the octal permission with a leading 0 (%#m
), the owning user (%u
) and the file name relative the the starting point (%p
).
Listing 3. Generating a list of files with suid set
[root@attic5-f33 ~]# find / -perm /4000 -fprintf /root/suid.txt '%#m %u %p\n' 2>/dev/null
[root@attic5-f33 ~]# ls -l /root/suid.txt
-rw-r--r--. 1 root root 904 Dec 4 17:25 /root/suid.txt
[root@attic5-f33 ~]# wc /root/suid.txt
26 78 904 /root/suid.txt
[root@attic5-f33 ~]# head -n 3 /root/suid.txt
04755 root /usr/bin/newgrp
04755 root /usr/bin/vmware-user-suid-wrapper
04755 root /usr/bin/chage
The find
command supports multiple output expressions separated by the ‘,’ operator. Listing 4 shows how to generate two file lists, one with the suid set and another with the sgid set. For this example in Listing 4, I use symbolic permissions for both search and output.
Listing 4. Generating suid and sgid lists in a single traversal
[root@attic5-f33 ~]# find / \
> \( -perm /4000 -fprintf /root/suid.txt '%#m %u %p\n' \) , \
> \( -perm -g=s -fprintf /root/sgid.txt '%#M %u %p\n' \) 2>/dev/nnull
[root@attic5-f33 ~]# head -n 3 /root/sgid.txt
drwxrwsr-x tss /run/tpm2-tss/eventlog
drwxr-sr-x root /run/log/journal
-rwxr-sr-x root /usr/bin/write
Set or change user passwords and password aging
Most users authenticate with a password when logging in to a system. Use the passwd
command to change your password. You must know your current password in order to change it to something else. A system administrator can also use the passwd
command to reset a forgotten password, set a temporary password that must be changed by a user during next login, specify the maximum number of days that a password can be used before it must be changed, lock a user out of the system, and other related tasks. The system administrator does not need to know a user’s current password. The passwords are actually stored in /etc/shadow in an encrypted form, so not even root can extract them.
If a user forgets his or her password, the system administrator will usually generate a temporary password that is not too complex and communicate this temporary password to the user in some fashion that doesn’t require logging into the account, perhaps face-to-face, telephone, text or email to some account not associated with the lost password. In most such case the administrator will generate a password that includes some random elements. In Listing 5, I show one simple example to generate a partially random password using the mktemp
command, and then set it for user brendan who has lost his password. I use the --stdin
option to read the password from stdin rather than typing it and then retyping it.
Listing 5. Resetting a user password
[root@attic5-f33 ~]# mktemp -u Pass0-XXX
Pass0-2Pr
[root@attic5-f33 ~]# echo Pass0-n0R | passwd --stdin brendan
Changing password for user brendan.
passwd: all authentication tokens updated successfully.
If you want a user to change the password before further using the system, use the -e
or the --expire
option to expire the password as shown in Listing 6.
Listing 6. Expiring a password
[root@attic5-f33 ~]# info passwd
[root@attic5-f33 ~]# passwd -e brendan
Expiring password for user brendan.
passwd: Success
Listing 7 shows what user brendan’s next login might look like.
Listing 7. Logging in when your password is expired
[ian@attic5-f33 l-lpic1-110-1]$ ssh brendan@attic5-f33
brendan@attic5-f33's password:
You are required to change your password immediately (administrator enforced).
You are required to change your password immediately (administrator enforced).
Last login: Mon Dec 7 22:49:43 2020 from 192.168.1.25
WARNING: Your password has expired.
You must change your password now and login again!
Changing password for user brendan.
Current password:
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
Connection to attic5-f33 closed.
You can set the maximum number of days a user is allowed to use a password before changing it, as well as the number of days in advance to issue a warning and the number of days (grace period) before the account is locked. You can also set the minimum number of days between password changes. You might want to do this if your system uses Pluggable Authentication Modules (PAMs) and you have set up rules that require a password not to match any of say the last twelve passwords. With this example requirement in place, a minimum password change period of 1 day ensures that a user cannot go back to a previously used password for at least 12 days. You can also display the current values for each duration. Either the passwd
or chage
command will do these tasks for you, although the parameter names differ between them. You can use chage
interactively if you prefer. Listing 8 shows some examples of each command. Consult the man or info pages for full details on all parameters.
Listing 8. Using passwd and chage to set password duration
[root@attic5-f33 ~]# # Set brendan's minimum and maximum password lifetime
[root@attic5-f33 ~]# passwd -n 1 -x 90 brendan
Adjusting aging data for user brendan.
passwd: Success
[root@attic5-f33 ~]# # Set a 7 day warning period and a 14 day grace period
[root@attic5-f33 ~]# chage -W 8 -I 14 brendan
[root@attic5-f33 ~]# # Compare the settings for brendan and ian
[root@attic5-f33 ~]# passwd -S brendan
brendan PS 2020-12-07 1 90 8 14 (Password set, SHA512 crypt.)
[root@attic5-f33 ~]# passwd -S ian
ian PS 2020-12-01 0 99999 7 -1 (Password set, SHA512 crypt.)
[root@attic5-f33 ~]# # list settings using chage
[root@attic5-f33 ~]# chage -l brendan
Last password change : Dec 08, 2020
Password expires : Mar 08, 2021
Password inactive : Mar 22, 2021
Account expires : never
Minimum number of days between password change : 1
Maximum number of days between password change : 90
Number of days of warning before password expires : 8
Are you surprised that the output for chage -l
shows that brendan’s account never expires? The grace (or inactivity) period is the number of days after the password expires and before the password can no longer be used. The -l
and -u
options of passwd
respectively lock or unlock the password. Password locking is accomplished by prepending the encrypted password in /etc/shadow with a ‘!’ character, which renders it invalid but can be easily reversed. The second output field in passwd -S
changes to LK
to indicate a locked password. Because the encrypted password is invalid, the user will see a message such as “Permission denied, please try again.” when attempting to log in. Listing 9 shows some examples.
Listing 9. Locking and unlocking a password
[root@attic5-f33 ~]# passwd -l brendan
Locking password for user brendan.
passwd: Success
[root@attic5-f33 ~]# passwd -S brendan
brendan LK 2020-11-17 1 90 8 14 (Password locked.)
[root@attic5-f33 ~]# grep brendan /etc/shadow
brendan:!!$6$Pjwv1j/M63 ... iOOQ/ct/:18584:1:90:8:14::
[root@attic5-f33 ~]# passwd -u brendan
Unlocking password for user brendan.
passwd: Success
If a user has other means of logging in such as Secure Shell (SSH) authentication tokens, these can still be used to access the account. The -E
option of chage
is used to either set an expiration date after which the account can no longer be used, or reinstate it (using a value of -1). Finally, the -d
option of chage
allows you to set the date that a user last changed a password. Listing 10 shows how to set the last password change date and also disable the account. The second part of the listing shows what happens when brendan attempts to log in.
Listing 10. Disabling an account using chage
[root@attic5-f33 ~]# date +%F
2020-12-08
[root@attic5-f33 ~]# chage -d $(date -d '20 days ago' +%F) brendan
[root@attic5-f33 ~]# chage -E $(date -d '2 days ago' +%F) brendan
[root@attic5-f33 ~]# chage -l brendan
Last password change : Nov 18, 2020
Password expires : Feb 16, 2021
Password inactive : Mar 02, 2021
Account expires : Dec 06, 2020
Minimum number of days between password change : 1
Maximum number of days between password change : 90
Number of days of warning before password expires : 8
[ian@attic5-f33 l-lpic1-110-1]$ ssh brendan@attic5-f33
brendan@attic5-f33's password:
Your account has expired; please contact your system administrator.
Connection closed by 192.168.1.25 port 22
The passwd
and chage
commands listed above require root authority. Unprivileged users can use passwd
to change their own passwords and chage
with the -l
option to display their password status. So they can find out when their password expires without having to wait for a warning.
Some of these functions can also be done with the usermod
command. The -L
and -U
options lock and unlock a password by prepending a ‘!’ in /etc/shadow similar to the -l
and -u
options of the passwd
command. Check the man or info pages for more information and note, in particular, the -e
(expire date), -f
(inactive days), and -p
(password – not recommended) options.
Discover open ports on your system
Open ports on a system are ports that have some application listening. For example, web servers will usually have ports open for HTTP and HTTPS protocols and I have an SSH port open for administrative purposes. Use the nmap
command to probe open ports on a system. Some functions of nmap
work with non-root access, but many will require you to have root access. I use root access in these examples whether it is actually needed or not. Listing 11 shows the result of using nmap
on the local address and the Ethernet address for my Fedora 33 system. Use either a host name or an IP address for the system to scan.
Listing 11.Basic nmap examples
[root@attic5-f33 ~]# nmap localhost
Starting Nmap 7.80 ( https://nmap.org ) at 2020-12-10 18:59 EST
Nmap scan report for localhost (127.0.0.1)
Host is up (0.000015s latency).
Other addresses for localhost (not scanned): ::1
Not shown: 998 closed ports
PORT STATE SERVICE
22/tcp open ssh
631/tcp open ipp
Nmap done: 1 IP address (1 host up) scanned in 0.12 seconds
[root@attic5-f33 ~]#
[root@attic5-f33 ~]# nmap 192.168.1.25
Starting Nmap 7.80 ( https://nmap.org ) at 2020-12-10 18:59 EST
Nmap scan report for attic5-f33 (192.168.1.25)
Host is up (0.000011s latency).
Not shown: 999 closed ports
PORT STATE SERVICE
22/tcp open ssh
Nmap done: 1 IP address (1 host up) scanned in 0.17 seconds
If you don’t recognize a port number, try using the grep
command with /etc/services as shown in Listing 12.
Listing 12. What port is that?
[root@attic5-f33 ~]# grep '[[:blank:]]22\/' /etc/services
ssh 22/tcp # The Secure Shell (SSH) Protocol
ssh 22/udp # The Secure Shell (SSH) Protocol
ssh 22/sctp # SSH
[root@attic5-f33 ~]# grep '[[:blank:]]631\/' /etc/services
ipp 631/tcp # Internet Printing Protocol
ipp 631/udp # Internet Printing Protocol
These examples show that local users on my system can use ssh
, scp
, or sftp
over port 22 and connect a web browser to port 631 to manage printers using the CUPS graphical interface. From outside ,you can only access my system using ssh
.
Listing 13 shows some additional examples; first my local Slackware system and then two well-known web servers.
Listing 13. Mapping additional systems
[root@attic5-f33 ~]# # Check my Slackware system
[root@attic5-f33 ~]# nmap attic4
Starting Nmap 7.80 ( https://nmap.org ) at 2020-12-10 18:49 EST
Nmap scan report for attic4 (192.168.1.24)
Host is up (0.000041s latency).
Not shown: 997 closed ports
PORT STATE SERVICE
22/tcp open ssh
37/tcp open time
113/tcp open ident
MAC Address: 84:16:F9:04:7A:2A (Tp-link Technologies)
Nmap done: 1 IP address (1 host up) scanned in 0.16 seconds
[root@attic5-f33 ~]# # check a couple of web servers
[root@attic5-f33 ~]# nmap www.ibm.com
Starting Nmap 7.80 ( https://nmap.org ) at 2020-12-10 18:50 EST
Nmap scan report for www.ibm.com (104.102.193.57)
Host is up (0.020s latency).
Other addresses for www.ibm.com (not scanned): 2600:1408:5c00:3a2::b3a 2600:1408:5c00:384::b3a
rDNS record for 104.102.193.57: a104-102-193-57.deploy.static.akamaitechnologies.com
Not shown: 998 filtered ports
PORT STATE SERVICE
80/tcp open http
443/tcp open https
Nmap done: 1 IP address (1 host up) scanned in 4.62 seconds
[root@attic5-f33 ~]# nmap www.lpi.org
Starting Nmap 7.80 ( https://nmap.org ) at 2020-12-10 18:50 EST
Nmap scan report for www.lpi.org (65.39.134.146)
Host is up (0.035s latency).
Not shown: 997 filtered ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
443/tcp open https
Nmap done: 1 IP address (1 host up) scanned in 5.19 seconds
You may have noticed in these examples messages such as “Not shown: 998 filtered ports” or “Not shown: 997 closed ports”. By default, nmap
scans 1000 or the most commonly used ports and displays only the open ones. A port is reported as closed if the host responds with a TCP reset message, while a port is reported as filtered if there is no response (for example, when a firewall simply drops packets). Most systems today disallow Telnet connections as these are very insecure. You can check a specific port using the -p
option with either the port number or the port’s common name. This option supports a single port, a range or ports (such as 21-25, or a comma separated list, where list members may be individual ports or ranges. Use ‘*’ for a wildcard specification such as ‘http*’. Escape or quote the wildcard character to avoid shell interpretation of it. Listing 14 shows an example.
Listing 14. Checking specific ports
[root@attic5-f33 ~]#
[root@attic5-f33 ~]# nmap -p 22-25,ntp,'http*' lpi.org
Starting Nmap 7.80 ( https://nmap.org ) at 2020-12-11 21:47 EST
Nmap scan report for lpi.org (65.39.134.146)
Host is up (0.039s latency).
PORT STATE SERVICE
22/tcp open ssh
23/tcp filtered telnet
24/tcp filtered priv-mail
25/tcp filtered smtp
80/tcp open http
123/tcp filtered ntp
280/tcp filtered http-mgmt
443/tcp open https
591/tcp filtered http-alt
593/tcp filtered http-rpc-epmap
4180/tcp filtered httpx
8000/tcp filtered http-alt
8008/tcp filtered http
8080/tcp filtered http-proxy
8443/tcp filtered https-alt
8990/tcp filtered http-wmap
8991/tcp filtered https-wmap
Nmap done: 1 IP address (1 host up) scanned in 1.59 seconds
If you wish to limit the scan to only UDP or only TCP, prefix a port or port range with U: or T: as appropriate, for example -p U:53,111,137,T:21-25,80
.
If you want to see more detail use the -d
option. Use it two times if you want to see even more verbose detail. Listing 15 shows comparison output for an open port and a filtered port.
Listing 15. Using the -d option with nmap
[root@attic5-f33 ~]# nmap -p 22-23 -d lpi.org
Starting Nmap 7.80 ( https://nmap.org ) at 2020-12-11 21:51 EST
--------------- Timing report ---------------
hostgroups: min 1, max 100000
rtt-timeouts: init 1000, min 100, max 10000
max-scan-delay: TCP 1000, UDP 1000, SCTP 1000
parallelism: min 0, max 0
max-retries: 10, host-timeout: 0
min-rate: 0, max-rate: 0
---------------------------------------------
Initiating Ping Scan at 21:51
Scanning lpi.org (65.39.134.146) [4 ports]
Packet capture filter (device enp9s0): dst host 192.168.1.25 and (icmp or icmp6 or ((tcp or udp or sctp) and (src host 65.39.134.146)))
We got a TCP ping packet back from 65.39.134.146 port 443 (trynum = 0)
Completed Ping Scan at 21:51, 0.07s elapsed (1 total hosts)
Overall sending rates: 60.82 packets / s, 2311.29 bytes / s.
mass_rdns: Using DNS server 127.0.0.53
Initiating Parallel DNS resolution of 1 host. at 21:51
mass_rdns: 0.00s 0/1 [#: 1, OK: 0, NX: 0, DR: 0, SF: 0, TR: 1]
Completed Parallel DNS resolution of 1 host. at 21:51, 0.00s elapsed
DNS resolution of 1 IPs took 0.00s. Mode: Async [#: 1, OK: 0, NX: 1, DR: 0, SF: 0, TR: 1, CN: 0]
Initiating SYN Stealth Scan at 21:51
Scanning lpi.org (65.39.134.146) [2 ports]
Packet capture filter (device enp9s0): dst host 192.168.1.25 and (icmp or icmp6 or ((tcp or udp or sctp) and (src host 65.39.134.146)))
Discovered open port 22/tcp on 65.39.134.146
Completed SYN Stealth Scan at 21:51, 1.32s elapsed (2 total ports)
Overall sending rates: 2.27 packets / s, 99.90 bytes / s.
Nmap scan report for lpi.org (65.39.134.146)
Host is up, received syn-ack ttl 52 (0.036s latency).
Scanned at 2020-12-11 21:51:56 EST for 1s
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 52
23/tcp filtered telnet no-response
Final times for host: srtt: 36474 rttvar: 28663 to: 151126
Read from /usr/bin/../share/nmap: nmap-payloads nmap-services.
Nmap done: 1 IP address (1 host up) scanned in 1.50 seconds
Raw packets sent: 7 (284B) | Rcvd: 2 (88B)
The nmap
command first attempts to ping the target system. Some systems, including my Microsoft® Windows® 10 system do not respond to a ping (ICMP ECHO). The -Pm
option allows you to suppress the ping and continue with the scan anyway.
The nmap
command has a vast array of other options, including options to attempt detection of the operating system type of the target system and the level of software listening on the port. Consult the man or info pages for more details or refer to the online documentation listed in the Resources section for this tutorial.
You can find additional information about ports on your own system using the netstat
command. If you run it without any parameters, you will find a large number of UNIX® domain sockets within your system that are connected. Because you will most likely be interested in TCP or UDP connections to or from the outside world, you will generally want to use parameters such as -t
for TCP connections, -u
for UDP connections, or -l
for ports that are listening but not connected. By default, the report uses the service name, if known. Use the -n
option if you want numeric port numbers such as 22 instead of ssh
. Listing 16 shows an example on my Fedora 33 system.
Listing 16. Basic use of netstat
[root@attic5-f33 ~]# netstat -t
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 attic5-f33:47540 attic4:ssh ESTABLISHED
tcp 0 0 attic5-f33:39120 ec2-54-173-95-250:https ESTABLISHED
tcp 0 0 attic5-f33:37244 stackoverflow.com:https ESTABLISHED
tcp 0 0 attic5-f33:50860 ec2-52-37-190-150:https ESTABLISHED
tcp 1 0 attic5-f33:35326 ec2-3-211-216-81.:https CLOSE_WAIT
tcp 0 0 attic5-f33:40864 server-99-86-230-:https ESTABLISHED
tcp 0 0 attic5-f33:ssh attic4:38340 ESTABLISHED
tcp 0 0 attic5-f33:45014 ec2-54-158-98-5.c:https ESTABLISHED
tcp6 1 0 2603-6081-1902-7d:50684 iad23s87-in-x03.1:https CLOSE_WAIT
tcp6 1 0 2603-6081-1902-7d:43824 2606:4700::6812:1:https CLOSE_WAIT
tcp6 1 0 2603-6081-1902-7d:50336 2600:9000:2191:a0:https CLOSE_WAIT
tcp6 1 0 2603-6081-1902-7d:43728 2606:4700:10::681:https CLOSE_WAIT
[root@attic5-f33 ~]# netstat -tn
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 192.168.1.25:47540 192.168.1.24:22 ESTABLISHED
tcp 0 0 192.168.1.25:39120 54.173.95.250:443 ESTABLISHED
tcp 0 0 192.168.1.25:37244 198.252.206.25:443 ESTABLISHED
tcp 0 0 192.168.1.25:50860 52.37.190.150:443 ESTABLISHED
tcp 1 0 192.168.1.25:35326 3.211.216.81:443 CLOSE_WAIT
tcp 0 0 192.168.1.25:40864 99.86.230.113:443 ESTABLISHED
tcp 0 0 192.168.1.25:22 192.168.1.24:38340 ESTABLISHED
tcp 0 0 192.168.1.25:45014 54.158.98.5:443 ESTABLISHED
tcp6 1 0 2603:6081:1902:7d:50684 2607:f8b0:4004:829::443 CLOSE_WAIT
tcp6 1 0 2603:6081:1902:7d:43824 2606:4700::6812:173:443 CLOSE_WAIT
tcp6 1 0 2603:6081:1902:7d:50336 2600:9000:2191:a00::443 CLOSE_WAIT
tcp6 1 0 2603:6081:1902:7d:43728 2606:4700:10::6814::443 CLOSE_WAIT
[root@attic5-f33 ~]# netstat -u
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
udp 0 0 attic5-f33:bootpc _gateway:bootps ESTABLISHED
udp 0 0 attic5-f33:bootpc _gateway:bootps ESTABLISHED
[root@attic5-f33 ~]# netstat -l |wc
96 769 8200
In this example, you see several HTTPS connections from my browser as well as two SSH connections, one into my Slackware system, 192.168.1.24, and one out. In both cases the other end is my Fedora 33 system, 192.168.1.25.
Notice that there a few tcp6 entries signifying IPv6. Specify the -4 or -6 options if you want to see only IPv4 or IPv6 information. Listing 17 shows an example for IPv6 connections on the same system.
Listing 17. Displaying IPv6 connections using netstat
[root@attic5-f33 ~]# netstat -t -6
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp6 1 0 2603-6081-1902-7d:50684 iad23s87-in-x03.1:https CLOSE_WAIT
tcp6 1 0 2603-6081-1902-7d:43824 2606:4700::6812:1:https CLOSE_WAIT
tcp6 1 0 2603-6081-1902-7d:50336 2600:9000:2191:a0:https CLOSE_WAIT
tcp6 1 0 2603-6081-1902-7d:43728 2606:4700:10::681:https CLOSE_WAIT
[root@attic5-f33 ~]# netstat -u -6
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
[root@attic5-f33 ~]# netstat -l -6
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp6 0 0 [::]:hostmon [::]:* LISTEN
tcp6 0 0 [::]:ssh [::]:* LISTEN
tcp6 0 0 localhost:ipp [::]:* LISTEN
udp6 0 0 localhost:323 [::]:*
udp6 0 0 attic5-f3:dhcpv6-client [::]:*
udp6 0 0 [::]:60698 [::]:*
udp6 0 0 [::]:mdns [::]:*
udp6 0 0 [::]:hostmon [::]:*
raw6 0 0 [::]:ipv6-icmp [::]:* 7
raw6 0 0 [::]:ipv6-icmp [::]:* 7
By now you know to use the man or info pages to find more information and additional parameters that you can use.
Limit user login events, processes, and memory usage
A very long time ago in the early 1970s, I was writing Fortran code to design shock tunnel nozzles for supersonic gas flow experiments at the Australian National University. I would often work at nights during which time I discovered that my jobs would work for a while and then I could no longer start them. Somebody doing math algorithms was able to expand the memory available to his program until there was not enough memory left in the system for any other user to launch a job. Can you stop such a behavior on a multiuser Linux system? The answer is yes, using the ulimit
command. Perhaps the simplest way to introduce ulimit
is to use the command with the -a
option to list all the limits you have for your own account. Listing 18 shows an example from my Slackware system.
Listing 18. Showing various limits with ulimit
ian@attic4-sl42:~$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 31590
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 31590
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
User limits fall into two categories: Soft limits and hard limits. A soft limit allow users to increase or decrease their own limit up to the hard limit. A hard limit is exactly that limit beyond which non-system users cannot raise their own limits.
As an example of ulimit
in action, I will set the maximum soft and hard files sizes. The sizes are specified in blocks which are 1024 bytes each on my Slackware system. Listing 19 shows how to check the block size and then set the soft limit to 10,000 blocks and the hard limit to 25,000 blocks.
Listing 19. Setting soft and hard limits with ulimit
root@attic4-sl42:~# df /home
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/root 70425980 10505884 56319616 16% /
root@attic4-sl42:~# ulimit -Sf 10000
root@attic4-sl42:~# ulimit -Hf 25000
root@attic4-sl42:~# ulimit -Sa
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) 10000
pending signals (-i) 31590
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 31590
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
root@attic4-sl42:~# ulimit -Hf
25000
Now consider what happens if user joe tries to create a 30 MB file filled with random data as shown in Listing 20.
Listing 20. How ulimit affects a user
joe@attic4-sl42:~$ head -c 30M </dev/urandom >testfile
File size limit exceeded
joe@attic4-sl42:~$ ls -l testfile
-rw-r--r-- 1 joe users 10240000 Dec 14 13:44 testfile
joe@attic4-sl42:~$ ulimit -Sf 40000
-su: ulimit: file size: cannot modify limit: Invalid argument
joe@attic4-sl42:~$ ulimit -Hf
25000
joe@attic4-sl42:~$ ulimit -Sf $(ulimit -Hf) # Set to maximum allowed
joe@attic4-sl42:~$ head -c 30M </dev/urandom >testfile
File size limit exceeded
joe@attic4-sl42:~$ ls -l testfile
-rw-r--r-- 1 joe users 25600000 Dec 14 13:46 testfile
joe@attic4-sl42:~$ echo $(( 25000 * 1024 )) # 25000 blocks of 1K
25600000
The limits you set using ulimit
apply to all non-system users. If your system uses PAM authentication you also have some finer control over limits. Look at the file /etc/security/limits.conf or see the man or info pages for limits.conf.
Who has logged in and who is currently logged in
Often you want to know who all are using your system and what they are using. Linux usually maintains two files that contain information about logged-in users. The utmp file is often located in /var/run/utmp. It contains information about users who are currently using the system. There may also be other users as some programs do not use utmp logging. The wtmp file is usually located at /var/log/wtmp. The wtmp file records all login and logout activities as well as recording system reboots with a pseudo user of ‘~’. Both utmp and wtmp contain binary records in an identical format. A third file, btmp, if it exists, records failed login attempts. It is usually located at /var/log/btmp. Listing 21 shows these files on my Fedora 33 system.
Listing 21. Login recording files
[root@attic5-f33 ~]# ls -l /var/log/*tmp /var/run/utmp
-rw-rw----. 1 root utmp 4992 Dec 14 15:12 /var/log/btmp
-rw-rw-r--. 1 root utmp 134016 Dec 15 12:05 /var/log/wtmp
-rw-rw-r--. 1 root utmp 2688 Dec 15 12:05 /var/run/utmp
Four commands are commonly used to display information from these files.
- The
who
command by default displays information from the utmp file about currently logged-in users. A non-option parameter may specify another file such as wtmp. - The
w
command combines information from the utmp file and the /proc file system to display more information about logged in users. - The
last
command displays data about a current or a previous login activity from the wtmp file. - The
lasstb
command displays information about failed login attempts from the btmp file (if this file exists).
Listing 22 shows basic usage of the who
and w
commands. Add the -a
option to who to see additional information, including system reboot time. Add the -H
option to display column headings.
Listing 22. Using who and w
[root@attic5-f33 ~]# who
ian tty2 2020-11-29 16:44 (tty2)
ian pts/2 2020-12-08 19:19 (192.168.1.24)
brendan pts/4 2020-12-15 12:04 (192.168.1.25)
brendan tty4 2020-12-15 12:05
[root@attic5-f33 ~]# who -a
system boot 2020-11-29 14:40
run-level 5 2020-11-29 14:40
ian + tty2 2020-11-29 16:44 old 1810 (tty2)
ian + pts/2 2020-12-08 19:19 00:53 118838 (192.168.1.24)
pts/3 2020-12-10 17:36 144621 id=ts/3 term=0 exit=0
brendan + pts/4 2020-12-15 12:04 00:53 215341 (192.168.1.25)
brendan + tty4 2020-12-15 12:05 00:05 215433
[root@attic5-f33 ~]# who -a -H
NAME LINE TIME IDLE PID COMMENT EXIT
system boot 2020-11-29 14:40
run-level 5 2020-11-29 14:40
ian + tty2 2020-11-29 16:44 old 1810 (tty2)
ian + pts/2 2020-12-08 19:19 00:56 118838 (192.168.1.24)
pts/3 2020-12-10 17:36 144621 id=ts/3 term=0 exit=0
brendan + pts/4 2020-12-15 12:04 00:56 215341 (192.168.1.25)
brendan + tty4 2020-12-15 12:05 00:08 215433
[root@attic5-f33 ~]# w
13:00:29 up 15 days, 22:20, 4 users, load average: 0.25, 0.36, 0.35
USER TTY LOGIN@ IDLE JCPU PCPU WHAT
ian tty2 29Nov20 15days 0.04s 0.04s /usr/libexec/gnome-session-binary
ian pts/2 08Dec20 56:30 0.07s 0.01s ssh brendan@192.168.1.25
brendan pts/4 12:04 56:21 0.04s 0.04s -bash
brendan tty4 12:05 8:29 0.04s 0.00s cat
Both commands have several options that are further described in the man or info pages. One useful variant for who
is who am i
to find out who is using a terminal or terminal session. The -m
option does the same thing.
The last
command formats data from the wtmp file or another file such as utmp if the -f
option is specified. This can be a lot of output, so you can limit it to a specified number or the most recent entries using the -n
(or -num
) option. Listing 23 shows an example.
Listing 23. Basic use of the last command
ian@attic4-sl42:~$ last -n 10
ian pts/3 192.168.1.25 Sat Dec 12 21:05 still logged in
ian pts/4 :0 Sat Dec 12 21:02 - 21:04 (00:01)
ian pts/3 192.168.1.25 Thu Dec 10 16:52 - 21:05 (2+04:12)
ian pts/2 :0 Tue Dec 8 18:26 still logged in
ian pts/2 192.168.1.25 Wed Dec 2 12:58 - 12:58 (00:00)
ian pts/3 192.168.1.25 Tue Nov 24 17:50 - 17:54 (00:03)
ian pts/2 192.168.1.25 Tue Nov 24 13:50 - 13:50 (5+00:00)
ian pts/2 127.0.0.1 Tue Nov 24 13:15 - 13:16 (00:00)
ian pts/1 :0 Tue Nov 24 13:15 still logged in
ian pts/0 :0 Tue Nov 24 13:15 still logged in
wtmp begins Sun Nov 19 15:48:30 2017
Use the -t
(until time) option of the last
command to see who all logged in at a specific time. The time is specified as YYYYMMDDHHMMSS, although some newer systems allow more general time formats such as ‘yesterday’ or ‘3 days ago’. Users logged in at that time show as ‘still logged in’. Some versions of last
also have a -s
(since time) option to list users logged in since the specified time. In such cases, the -p
option combines the effect of -s
and -t
to display users logged in at the specific time. Some examples from Fedora 33 are shown in Listing 24.
Listing 24. Using times with last
[root@attic5-f33 ~]# last -t 20200525150000
ian tty2 tty2 Mon May 25 14:32 - down (00:17)
reboot system boot 5.6.13-300.fc32. Mon May 25 14:31 - 14:49 (00:17)
ian tty2 tty2 Fri May 22 18:29 - down (2+18:53)
ian tty2 tty2 Fri May 22 18:24 - 18:29 (00:04)
reboot system boot 5.6.13-300.fc32. Fri May 22 18:24 - 13:22 (2+18:58)
ian tty2 tty2 Fri May 22 18:21 - down (00:02)
reboot system boot 5.6.13-300.fc32. Fri May 22 18:21 - 18:23 (00:02)
ian tty2 tty2 Fri May 22 17:39 - down (00:41)
reboot system boot 5.6.13-300.fc32. Fri May 22 17:39 - 18:20 (00:41)
ian tty2 tty2 Fri May 22 16:54 - down (00:40)
reboot system boot 5.6.6-300.fc32.x Fri May 22 16:54 - 17:35 (00:41)
ian tty2 tty2 Fri May 22 10:45 - down (00:30)
reboot system boot 5.6.13-300.fc32. Fri May 22 10:44 - 11:15 (00:30)
ian tty2 tty2 Thu May 21 19:05 - down (15:38)
reboot system boot 5.6.6-300.fc32.x Thu May 21 19:03 - 10:44 (15:40)
wtmp begins Thu May 21 19:03:56 2020
[root@attic5-f33 ~]# last -s '7 days ago'
brendan tty4 Tue Dec 15 12:05 still logged in
brendan pts/4 192.168.1.25 Tue Dec 15 12:04 still logged in
brendan pts/4 192.168.1.25 Mon Dec 14 15:16 - 16:38 (01:22)
ian pts/4 192.168.1.28 Sat Dec 12 08:51 - 08:51 (00:00)
ian pts/4 192.168.1.25 Thu Dec 10 13:45 - 13:45 (00:00)
ian pts/3 192.168.3.22 Thu Dec 10 13:41 - 17:36 (03:54)
ian pts/2 192.168.1.24 Tue Dec 8 19:19 still logged in
wtmp begins Thu May 21 19:03:56 2020
[root@attic5-f33 ~]# last -p '7 days ago'
ian tty2 tty2 Sun Nov 29 16:44 still logged in
reboot system boot 5.8.17-200.fc32. Sun Nov 29 14:40 still running
wtmp begins Thu May 21 19:03:56 2020
The lastb
command has the same options as the last
command. It is not part of this set of objectives but I mention it for completeness. It requires the /var/log/btmp file to exist and to not be writable by others. If you have an SSH port open, or forwarded through your router to your system, you can use lastb
to see how many people are trying to hack into your system using brute-force attacks. Check out an intrusion prevention system, such as fail2ban, to help block some of these attacks.
Who is using files
Sometimes you need to know who is using a file and keeping it open such that you cannot cleanly do something such as unmount a file system. The lsof
command can list every open file on your system. This includes sockets and can include a large amount of data. So you generally want to have a specific purpose in mind when using lsof
. You can restrict output by user using the file, by name of the command using the file, and by port, among many other possibilities. Listing 25 shows how many lines of output the lsof
command produces on my system with no options.
Listing 25. How much lsof output?
[root@attic5-f33 ~]# lsof | wc
lsof: WARNING: can't stat() fuse.gvfsd-fuse file system /run/user/1000/gvfs
Output information may be incomplete.
lsof: WARNING: can't stat() fuse.gvfsd-fuse file system /run/user/1001/gvfs
Output information may be incomplete.
311816 3392503 43770989
You can exclude the error messages caused by the permission settings for the gvfs file systems using the -e
option Listing 26 shows how to list the open connections on port 22, the files open that are associated with a user running the cat
command, and the status of a specific file.
Listing 26. Using lsof
[root@attic5-f33 ~]# lsof -e /run/user/1000/gvfs -e /run/user/1001/gvfs -i TCP:22
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
sshd 916 root 5u IPv4 37936 0t0 TCP *:ssh (LISTEN)
sshd 916 root 6u IPv6 37944 0t0 TCP *:ssh (LISTEN)
sshd 223142 root 5u IPv4 3212396 0t0 TCP attic5-f33:ssh->attic4:40920 (ESTABLISHED)
sshd 223147 ian 5u IPv4 3212396 0t0 TCP attic5-f33:ssh->attic4:40920 (ESTABLISHED)
[root@attic5-f33 ~]# lsof -e /run/user/1000/gvfs -e /run/user/1001/gvfs -c cat
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
cat 218180 brendan cwd DIR 8,9 4096 2878760 /home/brendan
cat 218180 brendan rtd DIR 8,9 4096 2 /
cat 218180 brendan txt REG 8,9 37000 392787 /usr/bin/cat
cat 218180 brendan mem REG 8,9 223542144 392527 /usr/lib/locale/locale-archive
cat 218180 brendan mem REG 8,9 3222128 392896 /usr/lib64/libc-2.32.so
cat 218180 brendan mem REG 8,9 264360 392801 /usr/lib64/ld-2.32.so
cat 218180 brendan 0u CHR 4,4 0t0 2070 /dev/tty4
cat 218180 brendan 1w REG 8,9 0 2878082 /home/brendan/test-data
cat 218180 brendan 2u CHR 4,4 0t0 2070 /dev/tty4
[root@attic5-f33 ~]# lsof -e /run/user/1000/gvfs -e /run/user/1001/gvfs ~brendan/test-data
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
cat 218180 brendan 1w REG 8,9 0 2878082 /home/brendan/test-data
Another common use of lsof
is to find out which user or process might be stopping you from unmounting a file system. I keep all my LPIC-1 tutorials and research data on a separate file system that I can mount across several different systems as I work. Suppose I decide to unmount that file system mounted at ~ian/data. Listing 27 shows one way I might do it and how to use lsof
to find out who is stopping me.
Listing 27. Who is stopping umount?
[root@attic5-f33 ~]# df ~ian/data
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sdb2 128491172 72405540 49515648 60% /home/ian/data
[root@attic5-f33 ~]# umount /dev/sdb2
umount: /home/ian/data: target is busy.
[root@attic5-f33 ~]# lsof -e /run/user/1000/gvfs -e /run/user/1001/gvfs /dev/sdb2
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
oosplash 3204 ian cwd DIR 8,18 4096 4591924 /home/ian/data/lpic-1/l-lpic1-110-1
soffice.b 3239 ian cwd DIR 8,18 4096 4591924 /home/ian/data/lpic-1/l-lpic1-110-1
soffice.b 3239 ian 31uW REG 8,18 40186 4591941 /home/ian/data/lpic-1/l-lpic1-110-1/l-lpic1-110-1.odt
Not surprisingly, it is I who have an open document as I write this tutorial!
The lsof
package comes with a file called 00QUICKSTART with a large number of useful examples. It is probably located at /usr/share/doc/lsof/00QUICKSTART. If not, try running the locate 00QUICKSTART
command to find it.
Note: You may need to install the mlocate package to run the locate
command.
Use the fuser
command to find the process that is using one or more particular files. Use the -a
option if you want the output for all the files in your list, even if nobody is using any of them. Use the -k
option if you want to kill the process. Use the -u
option to see the username associated with the process ID. Figure 28 shows some basic examples. As usual, consult the man or info pages for additional information on other options.
Listing 28. Using fuser
[root@attic5-f33 ~]# fuser -a ~ian/bashrc ~brendan/test-data
Specified filename /home/ian/bashrc does not exist.
/home/ian/bashrc:
/home/brendan/test-data: 218180
[root@attic5-f33 ~]# fuser -u ~brendan/test-data
/home/brendan/test-data: 218180(brendan)
[root@attic5-f33 ~]# fuser -uk ~brendan/test-data
/home/brendan/test-data: 218180(brendan)
[root@attic5-f33 ~]# fuser -a ~brendan/test-data
/home/brendan/test-data:
Use and configure sudo
When you need to administer a system you usually need to run some commands with root authority. You already saw that the suid permission would allow you to do this, but there are only a limited number of special purpose commands that have this permission set. So your choices are to log in as root, become root temporarily, or gain root access for a single command. You may absolutely need to log in as the root user to fix problems, such as the one I had tonight when one of my hard drives failed. The system would not boot into graphical mode until I took that mount out of /etc/fstab. However, logging in as the root user, particularly with a graphical desktop, is not a great idea if you don’t need to do it. And if you connect to a system using SSH, you should generally not allow root login. Most SSH server installations today disallow this by default.
After you have logged in as a regular user, you can use the su
command to temporarily become another user, or the sudo
command to run a command as another user. These are rather loose descriptions of the differences between the commands, but many old system admins see them that way. In fact, either allow you to run a single command as another user or become another user for a series of commands. One major difference between the su
and sudo
commands is that you need the password of the user you want to become in order to use su
while you use your own password to authenticate using sudo
. When you use the su
command, provide a user name as a parameter. If no user name is provided, you are assumed to be a root user.. If no command is provided, you enter an interactive shell. If you use the -
, -l
or --login
options, the shell will be started as a login shell with an environment similar to a real login. Use the -c
option if you want to run a single command or script. Look at how some of the environment variables and the current working directory change in the examples in Listing 29.
Listing 29. Basic use of su
mian@attic5-u20:~$ su mary -c 'echo $HOME;pwd'
Password:
/home/mary
/home/ian
ian@attic5-u20:~$ su - mary -c 'echo $HOME;pwd'
Password:
/home/mary
/home/mary
ian@attic5-u20:~$ su - mary
Password:
mary@attic5-u20:~$ echo $HOME;pwd
/home/mary
/home/mary
mary@attic5-u20:~$ # Use ctrl-d or logout to exit
mary@attic5-u20:~$ logout
Debian-based systems use the ‘!’ password in /etc/shadow for the root user as I described when discussing about locking passwords in the section, Set or change user passwords and password aging. So it is not possible to become root on such a system using su
. You will see an authentication failure as shown in Listing 30 on my Ubuntu 20.04 LTS system.
Listing 30. Using su – on Debina-based systems
ian@attic5-u20:~$ su - -c 'echo $HOME;pwd'
Password:
su: Authentication failure
ian@attic5-u20:~$ su -
Password:
su: Authentication failure
For such systems you must use sudo
to do administrative tasks that you might otherwise do by logging in or becoming the root user. Other than having different parameters, there are some subtle differences between su
and sudo
. In particular, all environment variables may not be set as you might expect, even if you use the -i
or --login
option to run the shell specified by the target user’s /etc/passwd entry as a login shell. Consider the differences between running a single command and launching an interactive shell for another user as shown in Listing 31.
Listing 31. Using sudo
ian@attic5-u20:~$ sudo -u mary echo '$HOME';pwd
[sudo] password for ian:
$HOME
/home/ian
ian@attic5-u20:~$ sudo -i -u mary echo '$HOME';pwd
/home/mary
/home/ian
ian@attic5-u20:~$ sudo -i -u mary
mary@attic5-u20:~$ echo $HOME;pwd
/home/mary
/home/mary
mary@attic5-u20:~$ logout
Notice that I only entered my password once for all three invocations of sudo
as compared to having to enter it for each invocation of su
. Credentials are usually cached for a configurable amount of time, usually a few minutes. That makes it easier to run several commands in succession using sudo
.
Another difference between su
and sudo
is that it is configurable and commands that run using sudo
can be logged. Default installations often set up an initial user as a member of the admin group or the wheel group. These groups are often configured to give members full root authority. Other users, say database administrators or web server operators, may be limited in the commands they are allowed to run. Some users (such as mary in my examples) may have no authority at all as I show in Listing 32.
Listing 32. User mary trying to use sudo
mary@attic5-u20:~$ sudo -u ian ls
[sudo] password for mary:
mary is not in the sudoers file. This incident will be reported.
The configuration for sudo
is usually in /etc/sudoers with additional files possibly included from the /etc/sudoers.d directory. The permission bits on these files should be 0440 (ug=r) as shown in Listing 33.
Listing 33. Sudoers files and their permissions
ian@attic5-u20:~$ ls -l /etc/sudoers*
-r--r----- 1 root root 755 Feb 3 2020 /etc/sudoers
/etc/sudoers.d:
total 8
-r--r----- 1 root root 91 Jul 10 09:59 99-snapd.conf
-r--r----- 1 root root 958 Feb 3 2020 README
These files are read-only and need to be edited using the visudo
command. Traditionally, this used the vi
editor, but today other editors,such as nano
, may be the default. A plug-in model is used for sudo
. The plug-in configuration is either defaulted or found in sudo.conf.
The info pages for sudo run to nearly 3000 lines on my Ubuntu 20.04 LTS system. Much of the specification is in Extended Backus-Naur Form (EBNF) which is briefly explained within the pages. The main components of the sudoers file are aliases and user specifications. Aliases are essentially variables that can be combined in various ways to create user specifications. User specifications say who can do what and where. The file also contains some default values and specifications if logging is enabled.
There are four kinds of aliases: User_Alias, Runas_Alias, Host_Alias, and Cmnd_Alias. User aliases and runas aliases include user names, user numbers, groups and group IDs. Host aliases include host names and IP addresses. Cmnd (command) aliases are lists of commands that a user may run. The alias ALL for any of these matches all instances. A user specification is a line of the form: who where = (as_whom) what. The default sudoers entries on my Ubuntu 20.04 LTS system look as shown in Listing 34.
Listing 34. Typical default sudoers user specifications
# User privilege specification
root ALL=(ALL:ALL) ALL
# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL
For a brief introduction to explain how all this works together, I will create a rather trivial file /etc/sudoers/88-lpic-1 which will allow user mary to run the apt
command to install packages. This file illustrates the use of aliases and how to set up logging so that all sudo
commands and sessions are logged, except those for the reboot
or sudoreplay
commands. The visudo
command will check the syntax of your sudoers files on exit, but you can also check it with the -c
option. The example file and a check are shown in Listing 35. Note that alias names allow only upper case letters, numbers, and underscores. It must start with an uppercase letter.
Listing 35. Adding sudoer definitions and logging
ian@attic5-u20:~$ sudo cat /etc/sudoers.d/88-lpic-1
## Simple example for tutorial for LPIC-1 topic 110.1
User_Alias INSTALLERS = ian,mary
Cmnd_Alias PKGMGR = /usr/bin/apt
INSTALLERS ALL = (ALL) PKGMGR
## Enable logging
Defaults log_output
Defaults! /usr/bin/sudoreplay !log_output
Defaults! /sbin/reboot !log_output
##
ian@attic5-u20:~$ sudo visudo -c
/etc/sudoers: parsed OK
/etc/sudoers.d/88-lpic-1: parsed OK
/etc/sudoers.d/README: parsed OK
If other specifications are absent, sudo
input or output is logged in the /var/log/sudo-io/ directory.
Users can run the sudoreplay
command to list all available sessions and to replay them. The list may be long so you can filter by command name, username, from date or to date, and other criteria. Listing 36 shows some examples.
Listing 36. Using sudoreplay
an@attic5-u20:~$ sudo sudoreplay -l todate "Dec 16 17:51:27"
Dec 16 17:40:56 2020 : ian : TTY=/dev/pts/0 ; CWD=/home/ian ; USER=root ; TSID=000001 ; COMMAND=/usr/sbin/visudo -c
Dec 16 17:41:15 2020 : mary : TTY=/dev/pts/1 ; CWD=/home/mary ; USER=root ; TSID=000002 ; COMMAND=/usr/bin/apt install mlocate
Dec 16 17:42:33 2020 : ian : TTY=/dev/pts/0 ; CWD=/home/ian ; USER=root ; TSID=000003 ; COMMAND=/usr/bin/ls /var/log/sudo-io
Dec 16 17:51:04 2020 : ian : TTY=/dev/pts/0 ; CWD=/home/ian ; USER=root ; TSID=000004 ; COMMAND=/usr/bin/cat /etc/sudoers/88-lpic-1
Dec 16 17:51:27 2020 : ian : TTY=/dev/pts/0 ; CWD=/home/ian ; USER=root ; TSID=000005 ; COMMAND=/usr/bin/cat /etc/sudoers/88-lpic-1
ian@attic5-u20:~$ info sudoreplay
ian@attic5-u20:~$ sudo sudoreplay -l user mary
Dec 16 17:41:15 2020 : mary : TTY=/dev/pts/1 ; CWD=/home/mary ; USER=root ; TSID=000002 ; COMMAND=/usr/bin/apt install mlocate
ian@attic5-u20:~$ sudo sudoreplay 000002
Replaying sudo session: /usr/bin/apt install mlocate
Reading package lists... Done
Building dependency tree
Reading state information... Done
mlocate is already the newest version (0.26-3ubuntu3).
0 upgraded, 0 newly installed, 0 to remove and 6 not upgraded.
The man or info pages for su
, sudoers
, visudo
, and sudoreplay
provide much more information than I can include in this tutorial. The Sudo Main Page (see Resources) is also a wealth of information.
Conclusion
This concludes your introduction to Topic 110.1: Perform security administration tasks.