Uji secara efisien apakah port terbuka di Linux?

197

Dari skrip bash bagaimana saya bisa dengan cepat mengetahui apakah port 445terbuka / mendengarkan di server.

Saya telah mencoba beberapa opsi, tetapi saya menginginkan sesuatu yang cepat:
1. lsof -i :445 (Membutuhkan detik)
2. netstat -an |grep 445 |grep LISTEN(Membutuhkan detik)
3. telnet(tidak kembali)
4. nmap, netcattidak tersedia di server

Akan menyenangkan mengetahui cara yang tidak disebutkan pertama dan menggerutu setelah itu.

Aman Jain
sumber
1
Apakah netcat tersedia? Ini memiliki jalur gagal IIRC yang cepat. netcat.sourceforge.net
JimR
5
netstat -lnt(dengan -tdan tanpa -a) akan membatasi output hanya untuk mendengarkan koneksi TCP. Mungkin sedikit mempercepat. Anda dapat menambahkan -4untuk IPv4 hanya jika Anda tidak membutuhkan IPv6.
Bartosz Moczulski
lsof -i adalah favorit pribadi.
Matt Joyce
14
netstat -an | grep PORTNUMBER | grep -i listenJika output kosong, port tidak digunakan.
automatix
Saya tidak tahu mengapa lsoflambat bagi Anda, tetapi biasanya ini adalah solusi terbaik yang Anda daftarkan. netstatSolusi Anda tidak terlalu andal (Anda dapat menebaknya kapan saja Anda gunakan grep; toh itu akan kembali benar jika seseorang mendengarkan misalnya 4450). telnetdan netcatsebenarnya berusaha membuat koneksi, yang mungkin tidak selalu seperti yang Anda inginkan.
petersohn

Jawaban:

155

Kejutan yang saya temukan baru-baru ini adalah bahwa Bash secara native mendukung koneksi tcp sebagai deskriptor file . Menggunakan:

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

Saya menggunakan 6 sebagai deskriptor file karena 0,1,2 adalah stdin, stdout, dan stderr. 5 kadang-kadang digunakan oleh Bash untuk proses anak , jadi 3,4,6,7,8, dan 9 harus aman.

Sesuai komentar di bawah ini, untuk menguji mendengarkan di server lokal dalam skrip:

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

Untuk menentukan apakah seseorang mendengarkan, cobalah untuk terhubung dengan loopback. Jika gagal, maka port ditutup atau kami tidak diizinkan mengakses. Setelah itu, tutup koneksi.

Ubah ini untuk kasus penggunaan Anda, seperti mengirim email, keluar dari skrip pada kegagalan, atau memulai layanan yang diperlukan.

Spencer Rathbun
sumber
2
Ini hanya digantung untukku.
Aman Jain
@AmanJain cat menunggu EOF atau Ctrl-C untuk berhenti. Anda harus menyesuaikan ini untuk protokol Anda. BTW apakah Anda menjalankan ini ke server jauh?
Spencer Rathbun
Saya ingin menanamkan kode pemeriksaan port dalam sebuah skrip di server, di bawah /etc/init.d/
Aman Jain
@AmanJain Saya sudah memperbaruinya untuk sistem lokal. Anda hanya ingin memeriksa apakah itu mendengarkan dengan benar? Tidak ada pemeriksaan protokol, seperti meminta halaman melalui http?
Spencer Rathbun
1
Ini bukan metode yang dapat diandalkan karena tidak semua OS (mis. Ubuntu 16 seperti yang saya temukan hari ini) dikirimkan dengan bash yang dikompilasi untuk membangun /dev/tcp/IP/PORTpohon
dyasny
107

Ada yang sangat singkat dengan "jawaban cepat" di sini: Bagaimana cara menguji apakah port TCP jarak jauh dibuka dari skrip Shell?

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

Saya menggunakannya dengan 127.0.0.1 sebagai alamat "jarak jauh".

ini mengembalikan "0" jika port terbuka dan "1" jika port ditutup

misalnya

nc -z 127.0.0.1 80; echo $?

-z Menentukan bahwa nc harus memindai untuk mendengarkan daemon, tanpa mengirim data apa pun kepada mereka. Merupakan kesalahan untuk menggunakan opsi ini bersamaan dengan opsi -l.

Hitam
sumber
2
Itu sepertinya cara termudah, terima kasih. Tautan skrip sampel tidak berfungsi lagi, namun cukup jelas.
derFunk
Bagus! Ini jauh lebih cepat daripada jawaban lain di server dengan banyak port terbuka. Kembali dalam <0,01 detik untuk saya sementara netstat / lsof mengambil 1s +
Tim
2
Bendera -z tidak tersedia di ncat berbasis nmap yang dikirimkan oleh distro terbaru: Fedora, Centos, dll. (Nmap-ncat-6.01-9.fc18.x86_64)
Zack
9
Konter-intuitif, ini mengembalikan "0" jika port terbuka dan "1" jika port ditutup.
Sean
3
Perintah @Sean unix biasanya mengembalikan '0' untuk menunjukkan keberhasilan dan bukan nol untuk kegagalan. Jadi '0' menunjukkan bahwa ia berhasil terhubung dan tidak nol sehingga tidak terhubung karena suatu alasan. Perhatikan, bagaimanapun, bahwa beberapa versi 'nc' tidak mendukung argumen '-z' sehingga stackoverflow.com/a/25793128/6773916 bisa dibilang merupakan solusi yang lebih baik.
Rich Sedman
89

Anda dapat menggunakan netstat dengan cara ini untuk hasil yang jauh lebih cepat:

Di Linux:

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

Di Mac:

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

Ini akan menampilkan daftar proses mendengarkan pada port (445 dalam contoh ini) atau tidak akan menghasilkan apa-apa jika port tersebut gratis.

anubhava
sumber
1
sintaks netstat Anda salah. netstat -ln --tcp bekerja, tapi masih lambat
Aman Jain
6
Sebenarnya itu sintaks yang benar tetapi mungkin Anda menggunakan Linux dan saya di Mac. Untuk Linux gunakan ini:netstat -lnt | awk '$6 == "LISTEN" && $4 ~ ".445"'
anubhava
21
ini tidak menghasilkan apa-apa.
Jürgen Paul
1
Pertanyaannya adalah tentang linux, jadi mungkin komentarnya ada di jawabannya.
UpTheCreek
1
Untuk memeriksa port 80, saya perlu menggunakan awk '$6 == "LISTEN" && $4 ~ "80$"'. Alih-alih memeriksa titik sebelum nomor port dengan \.80, saya menggunakan 80$. Jika tidak, ini juga cocok dengan alamat IP yang berisi .80dan port yang dimulai dengan 80seperti 8000.
Patrick Oscity
37

Anda dapat menggunakan netcat untuk ini.

nc ip port < /dev/null

terhubung ke server dan langsung menutup koneksi lagi. Jika netcat tidak dapat terhubung, ia akan mengembalikan kode keluar yang tidak nol. Kode keluar disimpan dalam variabel $ ?. Sebagai contoh,

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

akan mengembalikan 0 jika dan hanya jika netcat berhasil terhubung ke port.

Tony
sumber
1
Jawaban ini perlu lebih banyak upvotes. nc berfungsi dengan baik untuk kasus ini. Trik / dev / tcp pintar, tetapi tampaknya sulit untuk mengimplementasikan skrip dengan sinyal interupsi.
Avindra Goolcharan
5
ncmemiliki -zbendera untuk tujuan ini, yang tidak memerlukan input dari /dev/null. Sudah ada jawaban menggunakan -zbendera di atas.
Abe Voelker
2
@AbeVoelker Tidak semua versi nc mendukung flag -z. Saya menggunakan CentOS 7 dan menemukan solusi Tony untuk apa yang saya butuhkan.
Shadoninja
@Shadoninja Bagus untuk tahu! Jika saya bisa mengedit komentar kurang ajar dari 2014 saya akan.
Abe Voelker
'nc' tidak lagi mendukung '-z' dan jawaban ini tampaknya menjadi solusi terbaik.
Rich Sedman
18

Berdasarkan jawaban Spencer Rathbun, menggunakan bash:

true &>/dev/null </dev/tcp/127.0.0.1/$PORT && echo open || echo closed
pengguna1338062
sumber
Bagus, itu akan menekan pesan "Koneksi Ditolak". Keluar otomatis jika layanan menerima koneksi tanpa menunggu selamanya.
Seff
Solusi terbaik untuk layanan yang tidak mengirim data setelah koneksi baru. Sekitar 20 kali lebih cepat daripada memanggil netcat. Dapat dipersingkat untuk: &>/dev/null </dev/tcp/127.0.0.1/$PORT
ens
16

mereka terdaftar di / proc / net / tcp.

itu kolom kedua, setelah ":", dalam 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  

jadi saya kira salah satunya :50 di kolom ketiga harus stackoverflow: o)

lihat man 5 proclebih detail. dan memilih yang terpisah dengan sed dll dibiarkan sebagai latihan untuk pembaca yang lembut ...

andrew cooke
sumber
10
ss -tl4 '( sport = :22 )'

2ms cukup cepat?

Tambahkan titik dua dan ini berfungsi di Linux

leucos
sumber
2
Hebat, ssbahkan lebih cepat dari slighlty nc. ladalah untuk mendengarkan , 4untuk IPv4; sportsingkatan dari (tentu saja) port sumber . Perintah di atas mengasumsikan port TCP mendengarkan ( topsi): gunakan uopsi untuk UDP, atau tidak ada dari mereka untuk kedua protokol. Info lebih lanjut tentang ssseperti biasa di Nixcraft . CATATAN: ssfilter tidak berfungsi di sini, tidak tahu mengapa (bash 4.3.11, ss utility, iproute2-ss131122), harus menggunakan grep .
Campa
Sayang sekali ssperintah itu tidak mengembalikan kode keluar yang mencerminkan temuannya; selalu mengembalikan 0 kode keluar.
John Greene
| grep LISTEN?
leucos
Saya dapatkan State Recv-Q Send-Q Local Address:Port Peer Address:Portdan sekarang? Apa artinya ini?
Black
6

Inilah yang berfungsi untuk Mac dan Linux:

netstat -aln | awk '$6 == "LISTEN" && $4 ~ "[\\.\:]445$"'
Artur Bodera
sumber
Saya pikir Anda dapat menghapus [\\.\:].
Patrick Oscity
6
nc -l 8000

Di mana 8000 adalah nomor port. Jika port gratis, itu akan memulai server yang dapat Anda tutup dengan mudah. Jika tidak maka akan menimbulkan kesalahan:

nc: Address already in use
Jose Enrique
sumber
5

Saya ingin memeriksa apakah port terbuka di salah satu server pengujian linux kami. Saya dapat melakukannya dengan mencoba terhubung dengan telnet dari mesin dev saya ke server pengujian. Pada mesin dev coba jalankan:

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

Dalam contoh ini saya ingin memeriksa apakah port 8080 terbuka di host test2.host.com

Razvang
sumber
1

tcping adalah alat yang hebat dengan overhead yang sangat rendah. Ini juga memiliki argumen batas waktu untuk membuatnya lebih cepat:

[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.
Payam
sumber
1
Tidak yakin tcping layak dipasang ketika solusi Spencer tidak memerlukan instalasi tambahan, tetapi ini adalah solusi terbersih dan terbaca oleh manusia.
bdombro
1

Anda dapat menggunakan perintah netcat juga

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

atau

nc -zv [ip] [port]

-z - mengatur nc untuk hanya memindai daemon yang mendengarkan, tanpa benar-benar mengirim data apa pun kepada mereka.
-v - mengaktifkan mode verbose.

Saurabh
sumber
-2

nmapadalah alat yang tepat. Cukup gunakannmap example.com -p 80

Anda dapat menggunakannya dari server lokal atau jauh. Ini juga membantu Anda mengidentifikasi jika firewall memblokir akses.

zainengineer
sumber
-4

Jika Anda menggunakan iptables coba:

iptables -nL

atau

iptables -nL | grep 445
Noz
sumber
yang hanya mencantumkan aturan iptables ... yang mungkin tidak memiliki korelasi dengan port terbuka.
David Goodwin