Ефективно перевірити, чи не відкрито порт Linux?


197

З баш сценарію, як можна швидко дізнатися, чи відкритий порт 445/ прослуховується порт на сервері.

Я спробував пару варіантів, але хочу щось швидке:
1. lsof -i :445 (Займає секунди)
2. netstat -an |grep 445 |grep LISTEN(Займає секунди)
3. telnet(не повертається)
4. nmap, netcatнедоступні на сервері

Буде приємно знати спосіб, який не перераховується спочатку, а після цього - пропуски.


1
Чи доступний netcat? Він має швидкий провал IIRC. netcat.sourceforge.net
JimR

5
netstat -lnt-tі без -a) обмежить вихід лише на прослуховування TCP-з'єднань. Це може трохи прискорити. Ви можете додати -4для IPv4 лише тоді, коли вам не потрібен IPv6.
Бартош Мочульський

lsof -i - це особистий фаворит.
Метт Джойс

14
netstat -an | grep PORTNUMBER | grep -i listenЯкщо вихід порожній, порт не використовується.
automatix

Я не знаю, чому lsofвам повільно, але зазвичай це найкраще із перелічених вами рішень. Ваше netstatрішення не дуже надійне (ви можете здогадуватися про нього, коли ви використовуєте grep; все одно воно повернеться істинним, якщо хтось слухає, наприклад, 4450). telnetі netcatнасправді намагаються створити з'єднання, яке не завжди може бути таким, яким ви хочете.
petersohn

Відповіді:


155

Несподіванкою, яку я нещодавно з’ясував, є те, що Bash споконвічно підтримує з'єднання tcp як дескриптори файлів . Використовувати:

exec 6<>/dev/tcp/ip.addr.of.server/445
echo -e "GET / HTTP/1.0\n" >&6
cat <&6

Я використовую 6 як дескриптор файлів, оскільки 0,1,2 - це stdin, stdout та stderr. 5 іноді Bash використовується для дочірніх процесів , тому 3,4,6,7,8 і 9 повинні бути безпечними.

Відповідно до коментаря нижче, для перевірки на прослуховування на локальному сервері в сценарії:

exec 6<>/dev/tcp/127.0.0.1/445 || echo "No one is listening!"
exec 6>&- # close output connection
exec 6<&- # close input connection

Щоб визначити, хтось слухає, спробуйте підключитися за допомогою петлі. Якщо це не вдалося, порт закритий або нам заборонено доступ. Після цього перервіть з'єднання.

Змініть це для вашого випадку використання, наприклад, надіслати електронний лист, вийти зі скрипту при відмові або запустити потрібну послугу.


2
Це просто повісили для мене.
Аман Джайн

@AmanJain кішка чекає, коли EOF або Ctrl-C кинуть. Вам потрібно буде відкоригувати це для свого протоколу. BTW ти це запускаєш на віддалений сервер?
Спенсер Ратбун

Я хочу вставити код перевірки порту в скрипт на сервері, під /etc/init.d/
Aman Jain

@AmanJain Я оновив його для локальної системи. Ви просто хочете перевірити, чи правильно воно прослуховування? Немає жодної перевірки протоколу, наприклад запиту сторінки через http?
Спенсер Ратбун

1
Це не є надійним методом, оскільки не всі ОС (наприклад, ubuntu 16, як я виявив сьогодні) постачаються з bash, складеним для побудови /dev/tcp/IP/PORTдерева
діасний

107

Тут дуже короткий "швидкий відповідь": Як перевірити, чи відкритий віддалений порт TCP від ​​скрипту Shell?

nc -z <host> <port>; echo $?

Я використовую його з 127.0.0.1 як "віддалену" адресу.

це повертає "0", якщо порт відкритий, і "1", якщо порт закритий

напр

nc -z 127.0.0.1 80; echo $?

-z Вказує, що nc повинен просто перевіряти демонстрацію прослуховування, не надсилаючи їм ніяких даних. Помилково використовувати цю опцію спільно з опцією -l.


2
Здається, це найпростіший спосіб, дякую. Зразковий посилання сценарію вже не працює, але все-таки цілком самозрозуміло.
derFunk

Приємно! Це набагато швидше, ніж інші відповіді на сервері з відкритими великими портами. Повертається за <0,01 секунди для мене, тоді як netstat / lsof займає 1 с +
Тім

2
Прапор -z відсутній у ncat-базі ncat, з яким останні номери дистрибутивуються: Fedora, Centos тощо. (Nmap-ncat-6.01-9.fc18.x86_64)
Zack

9
Навмисно, це повертає "0", якщо порт відкритий, і "1", якщо порт закритий.
Шон

3
Команди @Sean unix, як правило, повертають "0", щоб вказувати на успіх і не дорівнює нулю для відмови. Отже, "0" вказує на те, що він успішно підключився і не є нульовим, що з певних причин не підключився. Однак зауважте, що деякі версії 'nc' не підтримують аргумент '-z', тому stackoverflow.com/a/25793128/6773916 , можливо, є кращим рішенням.
Багатий Седман

89

Ви можете використовувати netstat таким чином для набагато швидших результатів:

У Linux:

netstat -lnt | awk '$6 == "LISTEN" && $4 ~ /\.445$/'

На Mac:

netstat -anp tcp | awk '$6 == "LISTEN" && $4 ~ /\.445$/'

Це виведе список процесів, які прослуховуються на порту (445 у цьому прикладі) або нічого не виведе, якщо порт вільний.


1
ваш синтаксис netstat неправильний. netstat -ln --tcp працює, але все ще повільно
Аман Джайн

6
Насправді це правильний синтаксис, але, ймовірно, ви використовуєте Linux, і я на Mac. Для Linux використовуйте це:netstat -lnt | awk '$6 == "LISTEN" && $4 ~ ".445"'
anubhava

21
це нічого не виводило.
Юрген Пол

1
Питання стосувалося Linux, хоча, можливо, коментар повинен бути у відповіді.
UpTheCreek

1
Для того, щоб перевірити порт 80, мені потрібно було скористатися awk '$6 == "LISTEN" && $4 ~ "80$"'. Замість того, щоб перевірити крапку перед номером порту \.80, я використав 80$. В іншому випадку, це також відповідає IP-адресам, що містять .80і порти, починаючи з 80таких як 8000.
Патрік Осіті

37

Для цього можна використовувати netcat.

nc ip port < /dev/null

підключається до сервера і безпосередньо знову закриває з'єднання. Якщо netcat не в змозі підключитися, він повертає ненульовий код виходу. Код виходу зберігається у змінній $ ?. Як приклад,

nc ip port < /dev/null; echo $?

поверне 0, якщо і лише в тому випадку, якщо netcat зможе успішно підключитися до порту.


1
Ця відповідь потребує більшої кількості результатів. nc прекрасно працює в цьому випадку. фокус / dev / tcp розумний, але здається, що важко реалізувати сценарій із перериваннями сигналу.
Avindra Goolcharan

5
nc-zдля цього є прапор, який не потребує отримання даних /dev/null. Вже є відповідь, використовуючи -zпрапор вище.
Abe Voelker

2
@AbeVoelker Не всі версії nc підтримують прапор -z. Я на CentOS 7 і знайшов рішення Тоні таким, яким мені потрібно.
Шадоніня

@Shadoninja Приємно знати! Якби я міг відредагувати легковажну інформацію з мого коментаря з 2014 року, я би зміг.
Abe Voelker

'nc' більше не підтримує '-z', тому ця відповідь здається найкращим рішенням.
Багатий Седман

18

На основі відповіді Спенсера Ратбуна, використовуючи bash:

true &>/dev/null </dev/tcp/127.0.0.1/$PORT && echo open || echo closed

Добре, це придушить повідомлення "Підключення відмовлено". Автоматично виходить, якщо служба приймає з'єднання, не чекаючи вічно.
Seff

Найкраще рішення для служб, які не надсилають даних після нового з'єднання. Приблизно в 20 разів швидше, ніж викликати netcat. Може бути скорочений до: &>/dev/null </dev/tcp/127.0.0.1/$PORT
Енс

16

вони вказані в / proc / net / tcp.

це другий стовпчик після ":" у шістнадцятковій версії:

> cat /proc/net/tcp
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode                                                     
   0: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 10863 1 ffff88020c785400 99 0 0 10 -1                     
   1: 0100007F:0277 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 7983 1 ffff88020eb7b3c0 99 0 0 10 -1                      
   2: 0500010A:948F 0900010A:2328 01 00000000:00000000 02:00000576 00000000  1000        0 10562454 2 ffff88010040f7c0 22 3 30 5 3                   
   3: 0500010A:E077 5F2F7D4A:0050 01 00000000:00000000 02:00000176 00000000  1000        0 10701021 2 ffff880100474080 41 3 22 10 -1                 
   4: 0500010A:8773 16EC97D1:0050 01 00000000:00000000 02:00000BDC 00000000  1000        0 10700849 2 ffff880104335440 57 3 18 10 -1                 
   5: 0500010A:8772 16EC97D1:0050 01 00000000:00000000 02:00000BF5 00000000  1000        0 10698952 2 ffff88010040e440 46 3 0 10 -1                  
   6: 0500010A:DD2C 0900010A:0016 01 00000000:00000000 02:0006E764 00000000  1000        0 9562907 2 ffff880104334740 22 3 30 5 4                    
   7: 0500010A:AAA4 6A717D4A:0050 08 00000000:00000001 02:00000929 00000000  1000        0 10696677 2 ffff880106cc77c0 45 3 0 10 -1  

тож я здогадуюсь, що один із тих, хто :50знаходиться у третьому стовпчику, повинен бути stackoverflow: o)

подивіться man 5 procдетальніше. і вибір, що крім sed тощо, залишається вправою для ніжного читача ...


10
ss -tl4 '( sport = :22 )'

2 мс досить швидко?

Додайте двокрапку, і це працює в Linux


2
Чудовий, ssнавіть легкий швидше, ніж nc. lє для прослуховування , 4є для IPv4; sportозначає (звичайно) вихідний порт . Наведена вище команда передбачає прослуховування порту TCP ( tопція): використовувати uпараметр для UDP, або жоден з них для обох протоколів. Більше інформації про, ssяк завжди, про Nixcraft . ПРИМІТКА: ssфільтри тут не працюють, не знаю, чому (bash 4.3.11, утиліта ss, iproute2-ss131122), мають працювати з grep .
Кампа

Шкода, що ssкоманда не повертає код виходу, що відображає її знаходження; він завжди повертає 0 код виходу.
Джон Грін

| grep LISTEN?
leucos

Я отримую State Recv-Q Send-Q Local Address:Port Peer Address:Portі зараз? Що це означає?
Чорний


6
nc -l 8000

Де 8000 - номер порту. Якщо порт вільний, він запустить сервер, який ви зможете легко закрити. Якщо це не так, ви видасте помилку:

nc: Address already in use

5

Я хотів перевірити, чи не відкрито порт на одному з наших тестових серверів Linux. Мені вдалося це зробити, намагаючись підключитися до telnet з моєї програми Dev до тестового сервера. На вашій машині розробки спробуйте запустити:

$ telnet test2.host.com 8080
Trying 05.066.137.184...
Connected to test2.host.com

У цьому прикладі я хочу перевірити, чи порт 8080 відкритий на хості test2.host.com


1

tcping - це чудовий інструмент з дуже низькими накладними витратами. Він також має аргумент на час очікування, щоб зробити його швидшим:

[root@centos_f831dfb3 ~]# tcping 10.86.151.175 22 -t 1
10.86.151.175 port 22 open.
[root@centos_f831dfb3 ~]# tcping 10.86.150.194 22 -t 1
10.86.150.194 port 22 user timeout.
[root@centos_f831dfb3 ~]# tcping 1.1.1.1 22 -t 1
1.1.1.1 port 22 closed.

1
Не впевнений, що tcping варто встановлювати, коли рішення Спенсера не потребує додаткових встановлень, але це визначено найчистішим і зручним для людини рішенням.
bdombro

1

Ви також можете використовувати команду netcat

[location of netcat]/netcat -zv [ip] [port]

або

nc -zv [ip] [port]

-z - встановлює nc просто сканувати прослуховування демонів, фактично не надсилаючи їм ніяких даних.
-v - вмикає багатослівний режим.


-2

nmapє правильним інструментом. Просто використовуйтеnmap example.com -p 80

Ви можете використовувати його з локального або віддаленого сервера. Це також допомагає визначити, чи брандмауер блокує доступ.


-4

Якщо ви використовуєте iptables, спробуйте:

iptables -nL

або

iptables -nL | grep 445

що просто перелічує правила iptables ..., які можуть не мати кореляції з відкритими портами.
Девід Гудвін
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.