Kiểm tra hiệu quả nếu một cổng được mở trên Linux?


197

Từ một tập lệnh bash, làm thế nào tôi có thể nhanh chóng tìm ra liệu một cổng 445có mở / nghe trên máy chủ hay không.

Tôi đã thử một vài tùy chọn, nhưng tôi muốn một cái gì đó nhanh chóng:
1. lsof -i :445 (Mất vài giây)
2. netstat -an |grep 445 |grep LISTEN(Mất vài giây)
3. telnet(nó không quay trở lại)
4. nmap,netcat không khả dụng trên máy chủ

Sẽ thật tuyệt khi biết một cách không liệt kê trước và greps sau đó.


1
Là netcat có sẵn? Nó có một con đường thất bại nhanh chóng IIRC. netcat.sourceforge.net
JimR

5
netstat -lnt(có -tvà không có -a) sẽ giới hạn đầu ra chỉ nghe các kết nối TCP. Nó có thể tăng tốc một chút. Bạn chỉ có thể thêm -4cho IPv4 nếu bạn không cần IPv6.
Bartosz Mộczulski

lsof -i là một yêu thích cá nhân.
Matt Joyce

14
netstat -an | grep PORTNUMBER | grep -i listenNếu đầu ra trống, cổng không được sử dụng.
automatix

Tôi không biết tại sao lsoflại chậm đối với bạn, nhưng thông thường, đó là giải pháp tốt nhất bạn liệt kê. netstatGiải pháp của bạn không đáng tin cậy lắm (bạn có thể đoán nó bất cứ khi nào bạn sử dụng grep; dù sao nó cũng trả về đúng nếu có ai đó nghe trên ví dụ 4450). telnetnetcatthực sự cố gắng tạo một kết nối, có thể không phải luôn luôn là những gì bạn muốn.
petersohn

Câu trả lời:


155

Một điều ngạc nhiên tôi phát hiện ra gần đây là Bash vốn hỗ trợ các kết nối tcp dưới dạng mô tả tệp . Để sử dụng:

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

Tôi đang sử dụng 6 làm bộ mô tả tệp vì 0,1,2 là stdin, stdout và stderr. 5 đôi khi được Bash sử dụng cho các tiến trình con , vì vậy 3,4,6,7,8 và 9 nên an toàn.

Theo nhận xét dưới đây, để kiểm tra nghe trên máy chủ cục bộ trong tập lệnh:

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

Để xác định xem ai đó đang lắng nghe, hãy thử kết nối bằng loopback. Nếu thất bại, cổng sẽ bị đóng hoặc chúng tôi không được phép truy cập. Sau đó, đóng kết nối.

Sửa đổi điều này cho trường hợp sử dụng của bạn, chẳng hạn như gửi email, thoát khỏi tập lệnh khi không thành công hoặc bắt đầu dịch vụ được yêu cầu.


2
Điều này chỉ treo cho tôi.
Aman Jain

Mèo @AmanJain chờ EOF hoặc Ctrl-C thoát. Bạn sẽ cần điều chỉnh điều này cho giao thức của bạn. BTW bạn đang chạy này đến một máy chủ từ xa?
Spencer Rathbun

Tôi muốn nhúng mã kiểm tra cổng vào tập lệnh trên máy chủ, trong /etc/init.d/
Aman Jain

@AmanJain Tôi đã cập nhật nó cho một hệ thống cục bộ. Bạn chỉ muốn kiểm tra xem nó có nghe đúng không? Không có bất kỳ giao thức kiểm tra nào, chẳng hạn như yêu cầu một trang qua http?
Spencer Rathbun

1
Đây không phải là một phương pháp đáng tin cậy vì không phải tất cả các hệ điều hành (ví dụ như Ubuntu 16 như tôi đã khám phá ngày hôm nay) được vận chuyển với bash được biên dịch để xây dựng /dev/tcp/IP/PORTcây
dyasny

107

Có một câu rất ngắn với "câu trả lời nhanh" ở đây: Làm cách nào để kiểm tra xem cổng TCP từ xa có được mở từ tập lệnh Shell không?

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

Tôi sử dụng nó với 127.0.0.1 làm địa chỉ "từ xa".

cái này trả về "0" nếu cổng mở và "1" nếu cổng bị đóng

ví dụ

nc -z 127.0.0.1 80; echo $?

-z Chỉ định rằng nc chỉ nên quét để nghe daemon, mà không gửi bất kỳ dữ liệu nào cho họ. Đó là một lỗi khi sử dụng tùy chọn này kết hợp với tùy chọn -l.


2
Đó dường như là cách dễ nhất, cảm ơn. Liên kết tập lệnh mẫu không còn hoạt động nữa, nhưng dù sao nó cũng khá tự giải thích.
derFunk

Đẹp! Điều này nhanh hơn nhiều so với các câu trả lời khác trên một máy chủ có nhiều cổng được mở. Trả lại trong <0,01 giây cho tôi trong khi netstat / lsof mất 1 giây +
Tim

2
Cờ -z không có sẵn trong ncat dựa trên nmap mà các bản phân phối gần đây nhất gửi kèm theo: Fedora, Centos, v.v. (nmap-ncat-6.01-9.fc18.x86_64)
Zack

9
Theo trực giác, điều này trả về "0" nếu cổng được mở và "1" nếu cổng bị đóng.
Sean

3
Các lệnh unix @Sean thường trả về '0' để biểu thị thành công và khác không cho thất bại. Vì vậy, '0' chỉ ra rằng nó được kết nối thành công và khác không mà nó không kết nối vì một số lý do. Tuy nhiên, lưu ý rằng một số phiên bản của 'nc' không hỗ trợ đối số '-z' nên stackoverflow.com/a/25793128/6773916 được cho là một giải pháp tốt hơn.
Rich Sedman

89

Bạn có thể sử dụng netstat theo cách này để có kết quả nhanh hơn nhiều:

Trên Linux:

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

Trên máy Mac:

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

Điều này sẽ đưa ra một danh sách các quá trình lắng nghe trên cổng (trong ví dụ này là 445) hoặc nó sẽ không xuất ra gì nếu cổng đó là miễn phí.


1
cú pháp netstat của bạn không chính xác. netstat -ln --tcp hoạt động, nhưng vẫn chậm
Aman Jain

6
Thực tế đó là cú pháp đúng nhưng có lẽ bạn đang sử dụng Linux và tôi đang dùng Mac. Đối với Linux, hãy sử dụng điều này:netstat -lnt | awk '$6 == "LISTEN" && $4 ~ ".445"'
anubhava

21
cái này không có gì.
Jürgen Paul

1
Câu hỏi là về linux, vì vậy có lẽ bình luận nên có trong câu trả lời.
UpTheCux

1
Để kiểm tra cổng 80 tôi cần sử dụng awk '$6 == "LISTEN" && $4 ~ "80$"'. Thay vì kiểm tra dấu chấm trước số cổng với \.80, tôi đã sử dụng 80$. Mặt khác, điều này cũng phù hợp với các địa chỉ IP có chứa .80và các cổng bắt đầu 80như 8000.
Patrick Oscarity

37

Bạn có thể sử dụng netcat cho việc này.

nc ip port < /dev/null

kết nối với máy chủ và trực tiếp đóng lại kết nối. Nếu netcat không thể kết nối, nó sẽ trả về mã thoát khác không. Mã thoát được lưu trữ trong biến $?. Ví dụ

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

sẽ trả về 0 khi và chỉ khi netcat có thể kết nối thành công với cổng.


1
Câu trả lời này cần nhiều upvote hơn. nc hoạt động hoàn hảo cho trường hợp này. Thủ thuật / dev / tcp rất thông minh, nhưng có vẻ khó thực hiện tập lệnh có ngắt tín hiệu.
Avindra Goolcharan

5
nc-zcờ cho mục đích này, không yêu cầu lấy đầu vào từ /dev/null. Đã có câu trả lời bằng cách sử dụng -zcờ ở trên.
Abe Voelker

2
@AbeVoelker Không phải tất cả các phiên bản của nc đều hỗ trợ cờ -z. Tôi đang dùng CentOS 7 và thấy giải pháp của Tony là thứ tôi cần.
Shadoninja

@Shadoninja Thật tốt khi biết! Nếu tôi có thể chỉnh sửa flippant-ness khỏi nhận xét của tôi từ năm 2014 thì tôi sẽ làm.
Abe Voelker

'nc' không còn hỗ trợ '-z' và vì vậy câu trả lời này dường như là giải pháp tốt nhất.
Rich Sedman

18

Dựa trên câu trả lời của Spencer Rathbun, sử dụng bash:

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

Tốt, nó sẽ chặn thông báo "Kết nối bị từ chối". Tự động thoát nếu dịch vụ chấp nhận kết nối mà không phải chờ đợi mãi.
Seff

Giải pháp tốt nhất cho các dịch vụ không gửi dữ liệu sau khi kết nối mới. Nhanh hơn khoảng 20 lần so với gọi netcat. Có thể được rút ngắn xuống còn: &>/dev/null </dev/tcp/127.0.0.1/$PORT
ens

16

chúng được liệt kê trong / Proc / net / tcp.

đó là cột thứ hai, sau dấu ":", ở dạng hex:

> 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  

vì vậy tôi đoán một trong những người :50trong cột thứ ba phải là stackoverflow: o)

nhìn vào man 5 procđể biết thêm chi tiết và chọn điều đó ngoài sed v.v ... được để lại như một bài tập cho người đọc nhẹ nhàng ...


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

2ms là đủ nhanh?

Thêm dấu hai chấm và điều này hoạt động trên Linux


2
Tuyệt vời, ssthậm chí còn nhanh hơn nc. ldành cho nghe , 4dành cho IPv4; sportlà viết tắt của (tất nhiên) cổng nguồn . Lệnh trên đang giả sử một cổng TCP lắng nghe ( ttùy chọn): sử dụng utùy chọn cho UDP hoặc không có giao thức nào cho cả hai giao thức. Thông tin thêm về ssnhư mọi khi trên Nixcraft . LƯU Ý: sscác bộ lọc không hoạt động ở đây, không biết tại sao (bash 4.3.11, tiện ích ss, iproute2-ss131122), phải đi với grep .
Campa

Quá tệ là sslệnh không trả về mã thoát phản ánh tìm kiếm của nó; nó luôn trả về 0 mã thoát.
John Greene

| grep LISTEN?
leucos

Tôi nhận State Recv-Q Send-Q Local Address:Port Peer Address:Portvà bây giờ? Điều đó có nghĩa là gì?
Đen

6

Đây là một hoạt động cho cả Mac và Linux:

netstat -aln | awk '$6 == "LISTEN" && $4 ~ "[\\.\:]445$"'

Tôi nghĩ rằng bạn có thể loại bỏ một cách an toàn [\\.\:].
Patrick Oscarity

6
nc -l 8000

Trong đó 8000 là số cổng. Nếu cổng miễn phí, nó sẽ khởi động một máy chủ mà bạn có thể đóng dễ dàng. Nếu không, nó sẽ báo lỗi:

nc: Address already in use

5

Tôi muốn kiểm tra nếu một cổng được mở trên một trong các máy chủ thử nghiệm linux của chúng tôi. Tôi đã có thể làm điều đó bằng cách cố gắng kết nối với telnet từ máy dev của tôi đến máy chủ thử nghiệm. Trên máy dev của bạn hãy thử chạy:

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

Trong ví dụ này tôi muốn kiểm tra xem cổng 8080 có mở trên máy chủ test2.host.com không


1

tcping là một công cụ tuyệt vời với chi phí rất thấp. Nó cũng có một đối số hết thời gian để làm cho nó nhanh hơn:

[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
Không chắc chắn tcping có giá trị cài đặt khi giải pháp của Spencer không yêu cầu cài đặt thêm, nhưng đây là giải pháp sạch nhất và dễ đọc nhất cho con người.
bdombro

1

Bạn cũng có thể sử dụng lệnh netcat

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

hoặc là

nc -zv [ip] [port]

-z - đặt nc chỉ đơn giản là quét tìm daemon, mà không thực sự gửi bất kỳ dữ liệu nào cho chúng.
-v - cho phép chế độ dài dòng.


-2

nmaplà công cụ phù hợp. Đơn giản chỉ cần sử dụngnmap example.com -p 80

Bạn có thể sử dụng nó từ máy chủ cục bộ hoặc từ xa. Nó cũng giúp bạn xác định nếu tường lửa chặn truy cập.


-4

Nếu bạn đang sử dụng iptables, hãy thử:

iptables -nL

hoặc là

iptables -nL | grep 445

chỉ liệt kê các quy tắc iptables ... có thể không có mối tương quan nào với các cổng mở.
David Goodwin
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.