В этом уроке вы узнаете, как найти порт процесса, запущенного в системе Linux.

Это очень распространенная вещь, которую нам необходимо знать при управлении приложениями в Linux, особенно если они были настроены кем-то другим.

Как найти порт процесса, работающего в Linux?

Команда netstat позволяет просматривать соединения с нашими текущими системами Linux и предоставляет флаги, которые также показывают, с каким процессом связано определенное соединение. В выводе netstat вы также можете увидеть порт, открытый определенным процессом. Вы также можете увидеть, какие порты открыты в системе Linux, используя команды lsof, ss и fuser.

Вы узнаете, какие флаги netstat следует использовать для отображения порта, открытого процессом в Linux, а также о других приемах, которые могут оказаться очень полезными для управления системой Linux.

Мы также рассмотрим альтернативы netstat, такие как lsof, ss и fuser.

Давайте начнем!

Какие порты прослушиваются в Linux?

Я часто вижу, что концепция порта не так проста для понимания тем, кто только начинает изучать Linux.

Порт — это канал связи, открываемый в системе Linux при запуске процесса. Порты позволяют пользователям или программам за пределами системы Linux взаимодействовать с ним.

Все примеры в этом руководстве основаны на распространенном приложении, работающем в системах Linux, — веб-сервере Apache.

При запуске Apache открывает порты (обычно 80 или 443), которые позволяют пользователям получать доступ к статическому контенту или веб-страницам, размещенным в нашей системе Linux.

Порты представлены числами от 0 до 65535. В следующей таблице показано значение различных диапазонов портов:

Диапазон портовКак используются эти порты
от 0 до 1023Известные порты или системные порты.
Используются системными процессами для предоставления стандартных сетевых услуг.
Только процессы с привилегиями суперпользователя могут открыть порт в этом диапазоне в системе Linux.
1024 по 49151Зарегистрированные порты.
Эти порты назначаются IANA для определенных приложений (например, 1521 для Oracle).
Их можно открыть в системе без привилегий суперпользователя.
49152 по 65535Динамические или частные порты.
Они не могут быть зарегистрированы в IANA и используются для автоматического выделения эфемерных портов.

Файл /etc/services в Linux содержит сведения обо всех зарезервированных портах.

Например, с помощью команды grep найдем порт, назначенный протоколу SMTP:

[ec2-user@ip-172-31-1-2 ~]$ grep -i "^smtp" /etc/services 
smtp            25/tcp          mail
smtp            25/udp          mail

Как видите, порт 25 используется протоколом SMTP, это один из известных портов, учитывая, что его значение ниже 1023 (вы помните предыдущую таблицу?)

Еще одно понятие, связанное с понятием порта, — это сокет.

Что такое сокет Linux?

Сокет Linux — это комбинация IP-адреса, протокола (например, TCP или UDP) и порта. TCP означает Transmission Control Protocol (протокол управления передачей), UDP означает User Datagram Protocol (протокол пользовательских датаграмм).

Начнем с первой команды!

Команда Netstat для проверки прослушиваемых портов в Linux

Основная команда для проверки открытых портов в системе Linux — netstat.

Если я хочу проверить, какие порты открыты, я могу использовать команду netstat -na вместе с командой grep, чтобы отфильтровать только те порты, которые находятся в состоянии прослушивания:

[ec2-user@ip-172-31-1-2 ~]$ netstat -na | grep -w "LISTEN"
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN     
tcp6       0      0:::111                 :::*                    LISTEN     
tcp6       0      0:::22                  :::*                    LISTEN     

Команда grep использует флаг -w для сопоставления точного слова «LISTEN». Она не будет соответствовать строке, содержащей слово «LISTENING».

Но в выводе чего-то не хватает, я бы хотел увидеть, что означает каждый столбец…

[ec2-user@ip-172-31-1-2 ~]$ netstat -na | egrep -w "Local Address|LISTEN"
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN     
tcp6       0      0:::111                 :::*                    LISTEN     
tcp6       0      0:::22                  :::*                    LISTEN     

Используя egrep, я могу отфильтровать вывод с помощью логики ИЛИ, которая отображает строки, соответствующие либо «Local Address» (одно из имен столбцов), либо «LISTEN».

Вот значение основных столбцов:

  • Proto: протокол, используемый сокетом (tcp, udp и т. д.)
  • Локальный адрес: адрес и номер порта локального конца сокета.
  • Внешний адрес: адрес и номер порта удаленного конца сокета.
  • Состояние: состояние сокета (LISTEN, ESTABLISHED и т. д.)

Когда я смотрю на вывод команды netstat, я вижу список сокетов (протокол, IP-адрес и порт). И я также могу быстро увидеть, что на этом сервере Linux не запущен Apache Web Server.

Как?

Потому что я не вижу TCP-порта, который я мог бы связать с веб-сервером, например 80 или 443.

Давайте проверим состояние Apache с помощью команды systemctl:

[ec2-user@ip-172-31-1-2 ~]$ sudo systemctl status httpd
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
   Active: inactive (dead)
     Docs: man:httpd.service(8)

Как вы видите, Apache неактивен, давайте его запустим!

[ec2-user@ip-172-31-1-2 ~]$ sudo systemctl start httpd
[ec2-user@ip-172-31-1-2 ~]$ sudo systemctl status httpd
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
   Active: active (running) since Mon 2020-08-03 11:10:54 UTC; 13s ago
     Docs: man:httpd.service(8)
 Main PID: 5256 (httpd)
   Status: "Total requests: 0; Idle/Busy workers 100/0;Requests/sec: 0; Bytes served/sec:   0 B/sec"
   CGroup: /system.slice/httpd.service
           ├─5256 /usr/sbin/httpd -DFOREGROUND
           ├─5257 /usr/sbin/httpd -DFOREGROUND
           ├─5258 /usr/sbin/httpd -DFOREGROUND
           ├─5259 /usr/sbin/httpd -DFOREGROUND
           ├─5260 /usr/sbin/httpd -DFOREGROUND
           └─5261 /usr/sbin/httpd -DFOREGROUND

Aug 03 11:10:54 ip-172-31-1-2.....compute.internal systemd[1]: Starting The Apache HTTP Server...
Aug 03 11:10:54 ip-172-31-1-2.....compute.internal systemd[1]: Started The Apache HTTP Server.

А теперь вывод команды netstat:

[ec2-user@ip-172-31-1-2 ~]$ netstat -na | egrep -w "Local Address|LISTEN"
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN     
tcp6       0      0:::111                 :::*                    LISTEN     
tcp6       0      0:::80                  :::*                    LISTEN     
tcp6       0      0:::22                  :::*                    LISTEN     

На этот раз порт 80 находится в состоянии LISTEN.

Подтверждение порта Apache с помощью Netstat

Я почти уверен, что это порт веб-сервера Apache, но как я могу это подтвердить?

Команда netstat предоставляет дополнительный флаг для отображения PID и имени программы, к которой относится определенный сокет. Флаг -p, где p обозначает программу:

[ec2-user@ip-172-31-1-2 ~]$ netstat -nap | egrep -w "Local Address|LISTEN"
(No info could be read for "-p": geteuid()=1000 but you should be root.)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      -                   
tcp6       0      0:::111                 :::*                    LISTEN      -                   
tcp6       0      0:::80                  :::*                    LISTEN      -                   
tcp6       0      0:::22                  :::*                    LISTEN      -                   

Хм, я ожидал увидеть что-то рядом с LISTEN, что дало бы мне более подробную информацию о программах, открывающих каждый порт.

Как видите, значения столбца PID/Program name (идентификатор и имя процесса, которому принадлежит сокет) не видны.

Почему я ничего не вижу?

Это потому что…

Только владелец процесса и пользователь root могут получить подробную информацию о процессах, запущенных в системе Linux.

Итак, кто является владельцем процесса Apache? Команда ps может помочь нам это выяснить:

[ec2-user@ip-172-31-1-2 ~]$ ps -aef | grep httpd
root      5256     1  0 11:10?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache    5257  5256  0 11:10?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache    5258  5256  0 11:10?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache    5259  5256  0 11:10?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache    5260  5256  0 11:10?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache    5261  5256  0 11:10?        00:00:00 /usr/sbin/httpd -DFOREGROUND

Родительский процесс с PID 5256 был запущен пользователем root, а дочерние процессы — пользователем Apache.

Причина, по которой я не могу увидеть никаких подробностей о PID процессов, использующих команду netstat, заключается в том, что я запускаю команду как пользователь ec2.

Чтобы увидеть больше подробностей в выводе, мне нужно указать команду sudo перед командой netstat.

[ec2-user@ip-172-31-1-2 ~]$ sudo netstat -nap | egrep -w "Local Address|LISTEN"
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN      2675/rpcbind        
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      3322/sshd           
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      3160/master         
tcp6       0      0:::111                 :::*                    LISTEN      2675/rpcbind        
tcp6       0      0:::80                  :::*                    LISTEN      5256/httpd          
tcp6       0      0:::22                  :::*                    LISTEN      3322/sshd           

На этот раз результат намного лучше!

Я вижу, что процесс httpd с PID 5256 открыл порт 80.

Флаг -n в нашей команде netstat показывает адреса в числовой форме, это применимо как к IP-адресам, так и к портам.

Посмотрите на вывод, если убрать флаг -n:

[ec2-user@ip-172-31-1-2 ~]$ sudo netstat -ap | egrep -w "Local Address|LISTEN"
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:sunrpc          0.0.0.0:*               LISTEN      2675/rpcbind        
tcp        0      0 0.0.0.0:ssh             0.0.0.0:*               LISTEN      3322/sshd           
tcp        0      0 localhost:smtp          0.0.0.0:*               LISTEN      3160/master         
tcp6       0      0 [::]:sunrpc             [::]:*                  LISTEN      2675/rpcbind        
tcp6       0      0 [::]:http               [::]:*                  LISTEN      5256/httpd          
tcp6       0      0 [::]:ssh                [::]:*                  LISTEN      3322/sshd                 

Видите разницу?

Команда netstat — одна из наиболее часто используемых команд для проверки сетевых подключений в системе Linux.

Проверьте, открыт ли порт, с помощью Lsof

Команда lsof расшифровывается как «List of open files» и используется для вывода списка всех файлов, открытых процессами в Linux.

Но какое отношение файлы имеют к открытым портам?

Как я уже упоминал ранее…

В Linux все является файлами, а сокеты — это особые типы файлов.

Давайте посмотрим, как использовать команду lsof, чтобы узнать, какой порт открыт нашим веб-сервером Apache…

…не забудьте команду sudo, как я уже объяснял. Также помните, что PID для Apache в моей системе Linux — 5256:

[ec2-user@ip-172-31-1-2 ~]$ sudo lsof -p 5256 | grep LISTEN
httpd   5256 root    4u  IPv6           11070402      0t0      TCP *:http (LISTEN)

Флаг -p принимает в качестве аргумента PID процесса, для которого мы хотим узнать порт, а часть вывода TCP *:http показывает, что порт, открытый этим процессом, является портом http.

Что делать, если я хочу узнать номер порта, сопоставленный с http?

Вы можете добавить флаг -P, который отключает преобразование номеров портов в имена портов:

[ec2-user@ip-172-31-1-2 ~]$ sudo lsof -p 5256 -P | grep LISTEN
httpd   5256 root    4u  IPv6           11070402      0t0      TCP *:80 (LISTEN)

Это показывает, что процесс Apache открыл порт 80 на моем хосте Linux.

А что, если я хочу найти процесс, открывающий другой порт?

Я могу использовать флаг -i, который извлекает список файлов, соответствующих интернет-адресу, указанному после флага.

Общий синтаксис:

lsof -i:port_number

Давайте посмотрим на практике:

[ec2-user@ip-172-31-1-2 ~]$ sudo lsof -i:80
COMMAND  PID   USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
httpd   5256   root    4u  IPv6 11070402      0t0  TCP *:http (LISTEN)
httpd   5257 apache    4u  IPv6 11070402      0t0  TCP *:http (LISTEN)
httpd   5258 apache    4u  IPv6 11070402      0t0  TCP *:http (LISTEN)
httpd   5259 apache    4u  IPv6 11070402      0t0  TCP *:http (LISTEN)
httpd   5260 apache    4u  IPv6 11070402      0t0  TCP *:http (LISTEN)
httpd   5261 apache    4u  IPv6 11070402      0t0  TCP *:http (LISTEN)

В выводе команды lsof вы можете увидеть полезную информацию, такую ​​как имя процесса, PID и владельца пользователя.

Вы также можете передать несколько портов команде lsof:

[ec2-user@ip-172-31-1-2 ~]$ sudo lsof -i:80 -i:22
COMMAND   PID     USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
sshd     3322     root    3u  IPv4    20024      0t0  TCP *:ssh (LISTEN)
sshd     3322     root    4u  IPv6    20026      0t0  TCP *:ssh (LISTEN)
httpd    5256     root    4u  IPv6 11070402      0t0  TCP *:http (LISTEN)
httpd    5257   apache    4u  IPv6 11070402      0t0  TCP *:http (LISTEN)
httpd    5258   apache    4u  IPv6 11070402      0t0  TCP *:http (LISTEN)
httpd    5259   apache    4u  IPv6 11070402      0t0  TCP *:http (LISTEN)
httpd    5260   apache    4u  IPv6 11070402      0t0  TCP *:http (LISTEN)
httpd    5261   apache    4u  IPv6 11070402      0t0  TCP *:http (LISTEN)
sshd    10877     root    3u  IPv4 11166512      0t0  TCP ip-172-31-1-2.mydomain:ssh->31.127.78.158:57775 (ESTABLISHED)
sshd    10895 ec2-user    3u  IPv4 11166512      0t0  TCP ip-172-31-28-249.mydomain:ssh->31.127.78.158:57775 (ESTABLISHED)

Имеет ли это смысл?

Использование команды ss для поиска открытых портов в Linux

Что такое команда ss?

Команда ss похожа на команду netstat и может использоваться для получения сведений о сокетах в Linux.

Вы заметите флаги, похожие на флаги netstat.

Следующая команда показывает прослушиваемые сокеты (флаг -l), имя процесса (или процессов), открывающего сокет (флаг -p), и фильтры, основанные только на сокетах TCP (флаг -t).

[ec2-user@ip-172-31-1-2 ~]$ sudo ss -tlp
State  Recv-Q  Send-Q    Local Address:Port      Peer Address:Port                                                                                                                                                            
LISTEN 0       128             0.0.0.0:sunrpc         0.0.0.0:*      users:(("rpcbind",pid=2675,fd=8))                                                                                                                        
LISTEN 0       128             0.0.0.0:ssh            0.0.0.0:*      users:(("sshd",pid=3322,fd=3))                                                                                                                           
LISTEN 0       100           127.0.0.1:smtp           0.0.0.0:*      users:(("master",pid=3160,fd=13))                                                                                                                        
LISTEN 0       128                [::]:sunrpc            [::]:*      users:(("rpcbind",pid=2675,fd=11))                                                                                                                       
LISTEN 0       128                   *:http                 *:*      users:(("httpd",pid=5261,fd=4),("httpd",pid=5260,fd=4),("httpd",pid=5259,fd=4),("httpd",pid=5258,fd=4),("httpd",pid=5257,fd=4),("httpd",pid=5256,fd=4))  
LISTEN 0       128                [::]:ssh               [::]:*      users:(("sshd",pid=3322,fd=4))                               

Формат вывода также чем-то похож на вывод netstat, посмотрите на названия столбцов…

Чтобы также увидеть любой порт UDP в состоянии прослушивания, вы можете добавить флаг -u:

sudo ss -tulp

Теперь я хочу увидеть только процесс (или процессы), которые прослушивают порт 80.

Как это сделать с помощью ss?

Вот общий синтаксис команды ss:

ss [options] [ FILTER ]

Второй аргумент — это фильтр, давайте рассмотрим пример фильтра для порта 80:

[ec2-user@ip-172-31-1-2 ~]$ sudo ss -tlp 'sport =:80'
State                        Recv-Q                        Send-Q                                                 Local Address:Port                                                 Peer Address:Port                        
LISTEN                       0                             128                                                                *:http                                                            *:*                            users:(("httpd",pid=5261,fd=4),("httpd",pid=5260,fd=4),("httpd",pid=5259,fd=4),("httpd",pid=5258,fd=4),("httpd",pid=5257,fd=4),("httpd",pid=5256,fd=4))

В фильтре вы можете увидеть слово «спорт», оно обозначает исходный порт.

Как и в случае с любой другой командой, вы можете использовать команду man, чтобы увидеть более подробную информацию о ss.

И это не конец, есть еще одна команда!

Используйте команду Linux Fuser для поиска TCP-порта

Очень здорово, что Linux позволяет делать одно и то же разными способами!

Другой вариант — команда fuser.

Команда fuser идентифицирует процессы, использующие файлы или сокеты в системе Linux.

Его синтаксис:

fuser <port_name>/<protocol>

Итак, чтобы узнать PID процессов, открывающих TCP-порт 80, вы можете использовать следующую команду:

[ec2-user@ip-172-31-1-2 ~]$ sudo fuser http/tcp
http/tcp:             5256  5257  5258  5259  5260  5261

Вы также можете заменить http на 80:

[ec2-user@ip-172-31-1-2 ~]$ sudo fuser 80/tcp
80/tcp:               5256  5257  5258  5259  5260  5261

Затем вы можете использовать команду ps, чтобы просмотреть более подробную информацию о PID, возвращаемых командой fuser.

Но есть и более быстрый вариант…

Попробуйте передать флаг -v команде fuser:

[ec2-user@ip-172-31-1-2 ~]$ sudo fuser 80/tcp -v
                     USER        PID ACCESS COMMAND
80/tcp:              root       5256 F.... httpd
                     apache     5257 F.... httpd
                     apache     5258 F.... httpd
                     apache     5259 F.... httpd
                     apache     5260 F.... httpd
                     apache     5261 F.... httpd

И вуаля!

Вы также получите подробную информацию о процессах, открывающих порт 80. Очень полезно!

Заключение

Мы перебрали множество вариантов, чтобы открыть порт процессом Linux, а также чтобы PID начинались с номера порта.

Чтобы обеспечить безопасность вашей системы Linux, крайне важно знать все открытые в ней порты.

Почему?

Потому что службы, работающие на известных портах, могут быть использованы для получения доступа к вашей системе Linux в случае, если версия вашей службы подвержена уязвимостям.

Поэтому первым шагом к обеспечению безопасности вашего компьютера является отслеживание портов в состоянии LISTEN.

Какую команду вы предпочитаете использовать для поиска порта, открытого процессом? Netstat, lsof, ss или fuser?

Written by Иван Васильков

Системный администратор и DevOps с опытом 10+ лет.