Определение прослушивающих портов с использованием Python
При переводе некоторых сценариев из bash я сталкиваюсь со многими случаями использования netstat -an, чтобы определить, прослушивает ли один из наших сервисов. Хотя я знаю, что могу просто использовать subprocess.call или другой даже popen, я бы предпочел использовать pythonic решение, поэтому я не использую среду unix, в которой мы работаем.
Из того, что я прочитал, у модуля сокета должно быть что-то, но я не видел ничего, что проверяет прослушивание портов. Может быть, я не понимаю простой трюк, но до сих пор я знаю, как подключиться к сокету, и написать что-то, что позволяет мне знать, когда это соединение не удалось. Но не обязательно я нашел что-то, что специально проверяет порт, чтобы узнать, прослушивает ли он.
Есть идеи?
6 ответов
Как насчет попытки подключиться...
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
result = s.connect_ex(('127.0.0.1', 3306))
if result == 0:
print('socket is open')
s.close()
Я знаю, что этот вопрос старый, но я пишу это для начинающих. Если вы хотите определить порты прослушивания в вашей системе, вы можете использовать код ниже.
from socket import *
Port = 0 #First port.
while Port <= 65535: #Port 65535 is last port you can access.
try:
try:
Socket = socket(AF_INET, SOCK_STREAM, 0) #Create a socket.
except:
print("Error: Can't open socket!\n")
break #If can't open socket, exit the loop.
Socket.connect(("127.0.0.1", Port)) #Try connect the port. If port is not listening, throws ConnectionRefusedError.
Connected = True
except ConnectionRefusedError:
Connected = False
finally:
if(Connected and Port != Socket.getsockname()[1]): #If connected,
print("{}:{} Open \n".format("127.0.0.1", Port)) #print port.
Port = Port + 1 #Increase port.
Socket.close() #Close socket.
import psutil
connections = psutil.net_connections()
Ссылка: /questions/13071081/kak-mne-poluchit-dostup-k-dannyim-netstat-v-python/13071100#13071100
В Linux мы можем использовать strace, чтобы увидеть, что netstat -ln читает и анализирует различные значения из файловой системы / proc.
$ strace netstat -ln 2>&1| grep '/proc'
open("/proc/net/tcp", O_RDONLY) = 3
open("/proc/net/tcp6", O_RDONLY) = 3
open("/proc/net/udp", O_RDONLY) = 3
open("/proc/net/udp6", O_RDONLY) = 3
open("/proc/net/raw", O_RDONLY) = 3
open("/proc/net/raw6", O_RDONLY) = 3
open("/proc/net/unix", O_RDONLY) = 3
open("/proc/net/ipx/socket", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/proc/net/ipx", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/proc/net/ax25", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/proc/net/x25", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/proc/net/x25", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/proc/net/nr", O_RDONLY) = -1 ENOENT (No such file or directory)
Таким образом, вы можете просто прочитать эти файлы из Python и извлечь необходимые данные.
$ cat /proc/net/tcp
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
0: 00000000:0050 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 8190 1 00000000 300 0 0 2 -1
1: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 6458 1 00000000 300 0 0 2 -1
2: 0100007F:0277 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 10425 1 00000000 300 0 0 2 -1
3: 8D0BA8C0:8801 689255D1:01BB 01 00000000:00000000 00:00000000 00000000 1000 0 1680975 1 00000000 24 4 16 6 -1
4: 8D0BA8C0:D142 97E67D4A:01BB 06 00000000:00000000 03:000012E8 00000000 0 0 0 3 00000000
5: 8D0BA8C0:D1A1 96E67D4A:01BB 01 00000000:00000000 00:00000000 00000000 1000 0 1672130 1 00000000 24 4 18 5 -1
6: 8D0BA8C0:D148 97E67D4A:01BB 01 00000000:00000000 00:00000000 00000000 1000 0 1679875 1 00000000 24 4 20 5 -1
Сокеты прослушивания будут иметь удаленный адрес 00000000:0000
Адрес: пары портов указаны в шестнадцатеричном формате. Смотрите: * Как мне сопоставить каждую запись / proc / net / tcp с каждым открытым сокетом?
Вы можете сделать перекрестную ссылку с /proc//fd. Например, sshd работает на моем ноутбуке.
$ cat /var/run/sshd.pid
522
$ sudo ls -l /proc/522/fd
total 0
lrwx------ 1 root root 64 2011-09-15 21:32 0 -> /dev/null
lrwx------ 1 root root 64 2011-09-15 21:32 1 -> /dev/null
lrwx------ 1 root root 64 2011-09-15 21:32 2 -> /dev/null
lrwx------ 1 root root 64 2011-09-15 21:32 3 -> socket:[6456]
lrwx------ 1 root root 64 2011-09-15 21:32 4 -> socket:[6458]
Сокет 6456 соответствует индексу 6458, указанному во втором ряду / proc / net / tcp.
Таким образом, вы можете получить всю эту информацию из proc, но в итоге вы можете заново изобретать netstat -lntp
Вы можете попробовать подключиться к рассматриваемому порту или эмулировать netstat
,
Последнее будет зависеть от ОС. На Linux вы можете изучить /proc/net/tcp
, Это выглядит так:
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
0: 00000000:C809 00000000:0000 0A 00000000:00000000 00:00000000 00000000 117 0 8381 1 ffff8802f22a8000 300 0 0 2 -1
1: 00000000:16CC 00000000:0000 0A 00000000:00000000 00:00000000 00000000 1026 0 14336 1 ffff8802f2249440 300 0 0 2 -1
2: 00000000:006F 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 7876 1 ffff8802f2248000 300 0 0 2 -1
3: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 8163 1 ffff8802f3578000 300 0 0 2 -1
4: 0100007F:0277 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 981582 1 ffff8800d7a53600 300 0 0 2 -1
5: 00000000:0019 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 9129 1 ffff8802edc886c0 300 0 0 2 -1
6: 00000000:021A 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 9016 1 ffff8802edc88000 300 0 0 2 -1
7: 00000000:2B1C 00000000:0000 0A 00000000:00000000 00:00000000 00000000 1026 0 783709 1 ffff8803119cca40 300 0 0 2 -1
8: 00000000:977C 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 24292 1 ffff8802f224e540 300 0 0 2 -1
Вы ищете строки, которые имеют 0A
в st
("статус") столбец. Числа после двоеточия в local_address
- C809
, 16CC
etc - номера портов TCP (в шестнадцатеричном формате), на которых происходят прослушивающие процессы.
Я знаю, что опаздываю на несколько лет, но ни один из существующих ответов недостаточно хорош.
Я искал в Google хорошее, элегантное решение для той же проблемы, и ни один из уже опубликованных ответов не казался достаточно хорошим, вместо этого я нашел собственные решения и хочу опубликовать их здесь, чтобы помочь будущим читателям, которые будут перенаправлены сюда Google.
В большинстве операционных систем есть исполняемый файл с именем, который можно использовать для захвата портов прослушивания, в этом примере я использую Windows 10 и Python 3.9.6 x64, но это написано на Python, поэтому вы можете легко адаптировать его для своего собственного варианта использования.
Использование простого
netstat
будет очень медленным из-за разрешения имен с использованием
netstat -n
будет экспоненциально быстрее, потому что не тратит время на разрешение имен.
В Python 3.9.6 используйте
subproces.run()
для запуска вызовов ОС и использовать
capture_output=True
для захвата stdout, затем используйте
.stdout
свойство результирующего процесса для получения вывода, результат в двоичной форме, используйте
.decode()
получить строку.
Тогда результат должен выглядеть так:
Active Connections
Proto Local Address Foreign Address State
TCP 10.70.0.6:1134 40.83.240.146:443 ESTABLISHED
TCP 10.70.0.6:1283 117.18.232.200:443 CLOSE_WAIT
TCP 10.70.0.6:1609 198.252.206.25:443 ESTABLISHED
TCP 10.70.0.6:1621 198.252.206.25:443 ESTABLISHED
TCP 10.70.0.6:1691 74.125.24.102:443 ESTABLISHED
TCP 10.70.0.6:1727 142.251.10.94:443 ESTABLISHED
TCP 10.70.0.6:1728 142.251.10.100:443 TIME_WAIT
TCP 10.70.0.6:1731 172.217.194.119:443 TIME_WAIT
TCP 10.70.0.6:1735 74.125.24.113:443 ESTABLISHED
TCP 10.70.0.6:1787 104.244.42.130:443 ESTABLISHED
TCP 10.70.0.6:1796 151.101.1.69:443 ESTABLISHED
TCP 10.70.0.6:1797 151.101.196.193:443 ESTABLISHED
TCP 10.70.0.6:1799 74.125.130.132:443 ESTABLISHED
TCP 10.70.0.6:1800 198.252.206.25:443 ESTABLISHED
TCP 10.70.0.6:1805 3.209.45.230:443 TIME_WAIT
TCP 10.70.0.6:1806 3.219.6.82:443 TIME_WAIT
TCP 10.70.0.6:1807 3.211.239.214:443 TIME_WAIT
TCP 10.70.0.6:1816 140.82.113.26:443 ESTABLISHED
TCP 127.0.0.1:1053 127.0.0.1:1055 ESTABLISHED
TCP 127.0.0.1:1055 127.0.0.1:1053 ESTABLISHED
TCP 127.0.0.1:1057 127.0.0.1:1058 ESTABLISHED
TCP 127.0.0.1:1058 127.0.0.1:1057 ESTABLISHED
TCP 127.0.0.1:1061 127.0.0.1:1062 ESTABLISHED
TCP 127.0.0.1:1062 127.0.0.1:1061 ESTABLISHED
TCP 127.0.0.1:1763 127.0.0.1:1764 ESTABLISHED
TCP 127.0.0.1:1764 127.0.0.1:1763 ESTABLISHED
TCP 127.0.0.1:1766 127.0.0.1:1767 ESTABLISHED
TCP 127.0.0.1:1767 127.0.0.1:1766 ESTABLISHED
TCP 127.0.0.1:1810 127.0.0.1:2015 ESTABLISHED
TCP 127.0.0.1:1811 127.0.0.1:2015 ESTABLISHED
TCP 127.0.0.1:1820 127.0.0.1:1821 ESTABLISHED
TCP 127.0.0.1:1821 127.0.0.1:1820 ESTABLISHED
TCP 127.0.0.1:1829 127.0.0.1:9614 SYN_SENT
TCP 127.0.0.1:2015 127.0.0.1:1810 ESTABLISHED
TCP 127.0.0.1:2015 127.0.0.1:1811 ESTABLISHED
TCP 127.0.0.1:14845 127.0.0.1:14846 ESTABLISHED
TCP 127.0.0.1:14846 127.0.0.1:14845 ESTABLISHED
TCP 127.0.0.1:15004 127.0.0.1:15005 ESTABLISHED
TCP 127.0.0.1:15005 127.0.0.1:15004 ESTABLISHED
TCP 127.0.0.1:15013 127.0.0.1:15014 ESTABLISHED
TCP 127.0.0.1:15014 127.0.0.1:15013 ESTABLISHED
TCP 127.0.0.1:16976 127.0.0.1:16977 ESTABLISHED
TCP 127.0.0.1:16977 127.0.0.1:16976 ESTABLISHED
TCP 127.0.0.1:19278 127.0.0.1:19279 ESTABLISHED
TCP 127.0.0.1:19279 127.0.0.1:19278 ESTABLISHED
TCP 127.0.0.1:19280 127.0.0.1:19281 ESTABLISHED
TCP 127.0.0.1:19281 127.0.0.1:19280 ESTABLISHED
TCP 127.0.0.1:20695 127.0.0.1:21385 ESTABLISHED
TCP 127.0.0.1:21385 127.0.0.1:20695 ESTABLISHED
TCP 127.0.0.1:23460 127.0.0.1:23461 ESTABLISHED
TCP 127.0.0.1:23461 127.0.0.1:23460 ESTABLISHED
TCP 127.0.0.1:23462 127.0.0.1:23463 ESTABLISHED
TCP 127.0.0.1:23463 127.0.0.1:23462 ESTABLISHED
TCP 127.0.0.1:28343 127.0.0.1:28344 ESTABLISHED
TCP 127.0.0.1:28344 127.0.0.1:28343 ESTABLISHED
TCP 127.0.0.1:30307 127.0.0.1:30308 ESTABLISHED
TCP 127.0.0.1:30308 127.0.0.1:30307 ESTABLISHED
TCP 127.0.0.1:30311 127.0.0.1:30312 ESTABLISHED
TCP 127.0.0.1:30312 127.0.0.1:30311 ESTABLISHED
TCP 127.0.0.1:30313 127.0.0.1:30314 ESTABLISHED
TCP 127.0.0.1:30314 127.0.0.1:30313 ESTABLISHED
TCP 127.0.0.1:30316 127.0.0.1:30317 ESTABLISHED
TCP 127.0.0.1:30317 127.0.0.1:30316 ESTABLISHED
TCP 127.0.0.1:30319 127.0.0.1:30320 ESTABLISHED
TCP 127.0.0.1:30320 127.0.0.1:30319 ESTABLISHED
TCP 127.0.0.1:30584 127.0.0.1:30585 ESTABLISHED
TCP 127.0.0.1:30585 127.0.0.1:30584 ESTABLISHED
TCP 127.0.0.1:30623 127.0.0.1:30624 ESTABLISHED
TCP 127.0.0.1:30624 127.0.0.1:30623 ESTABLISHED
TCP 127.0.0.1:49669 127.0.0.1:49670 ESTABLISHED
TCP 127.0.0.1:49670 127.0.0.1:49669 ESTABLISHED
TCP 127.0.0.1:49690 127.0.0.1:49692 ESTABLISHED
TCP 127.0.0.1:49692 127.0.0.1:49690 ESTABLISHED
TCP [::1]:3306 [::1]:23468 ESTABLISHED
TCP [::1]:3306 [::1]:23469 ESTABLISHED
TCP [::1]:23468 [::1]:3306 ESTABLISHED
TCP [::1]:23469 [::1]:3306 ESTABLISHED
Использовать
splitlines()
чтобы получить отдельные строки, затем используйте нарезку списка, чтобы получить содержимое фактической таблицы, здесь мы используем индекс 4, затем используем разделение регулярных выражений для разделения на пробельные символы, затем используйте индекс для получения значения локального адреса, затем, наконец, используйте разделение строк на двоеточия и индексация для получения портов.
Код:
import psutil
import re
import subprocess
def get_active_ports():
process = subprocess.run(['netstat', '-n'], capture_output=True)
report = process.stdout.decode().splitlines()
ports = set()
for i in report[4:]:
ports.add(re.split(':(?!.*:)', re.split('\s+', i)[2])[1])
return ports
Или однострочным:
set([re.split(':(?!.*:)', re.split('\s+', i)[2])[1] for i in subprocess.run(['netstat', '-n'], capture_output=True).stdout.decode().splitlines()[4:]])
Представление:
In [119]: %timeit set([re.split(':(?!.*:)', re.split('\s+', i)[2])[1] for i in subprocess.run(['netstat', '-n'], capture_output=True).stdout.decode().splitlines()[4:]])
11.4 ms ± 315 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Или, альтернативно,
psutil
имеет
.net_connections()
метод, вы можете просто получить от него порты.
Просто используйте понимание набора, чтобы получить результат:
set(i.laddr.port for i in psutil.net_connections())
Этот подход намного быстрее, чем предыдущий:
In [103]: %timeit set(i.laddr.port for i in psutil.net_connections())
893 µs ± 13.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)