В этом уроке вы узнаете, как найти порт процесса, запущенного в системе 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?