web-dev-qa-db-ja.com

リモートシステムのポートが到達可能かどうかをテストします(telnetなしで)

昔は、リモートホスト上のポートが開いているかどうかを確認するためにtelnetを使用しました。telnet hostname portは、任意のホスト上の任意のポートに接続しようとし、生のTCPストリームにアクセスできるようにします。

最近では、私が取り組んでいるシステムにはtelnetがインストールされておらず(セキュリティ上の理由から)、すべてのホストへのすべてのアウトバウンド接続はデフォルトでブロックされています。時間の経過とともに、どのポートがどのホストに対して開かれているのかがわからなくなります。

リモートシステムのポートが開いているかどうかをテストする別の方法はありますか - インストールされているパッケージの数が限られているLinuxシステムを使用していて、telnetが使用できないのですか?

330
Steve HHH

Bashは TCPUDP のポートにアクセスすることができました。しばらくの間。 manページから:

/dev/tcp/Host/port
    If Host is a valid hostname or Internet address, and port is an integer port number
    or service name, bash attempts to open a TCP connection to the corresponding socket.
/dev/udp/Host/port
    If Host is a valid hostname or Internet address, and port is an integer port number
    or service name, bash attempts to open a UDP connection to the corresponding socket.

だからあなたはこのようなものを使用することができます:

xenon-lornix:~> cat < /dev/tcp/127.0.0.1/22
SSH-2.0-OpenSSH_6.2p2 Debian-6
^C pressed here

タアダ!

263
lornix

素晴らしく冗長です。 manページから.
シングルポート:

nc -zv 127.0.0.1 80

複数のポート

nc -zv 127.0.0.1 22 80 8080

ポートの範囲

nc -zv 127.0.0.1 20-30
380

Netcatは便利なツールです。

nc 127.0.0.1 123 &> /dev/null; echo $?

ポート123が開いていれば0を、閉じていれば1を出力します。

100
thnee

socatのような他のツールを使わない最も簡単な方法は、上記の@ lornixの答えで説明されている通りです。これは、例えば他のサーバがコマンドラインからアクセス可能なポートにアクセスできるかどうかをテストしたい場合に、Bash内でpsuedo-device /dev/tcp/...をどのように利用するかの実際の例を追加することです。

自分のネットワーク上にskinnerという名前のホストがあるとします。

$ (echo > /dev/tcp/skinner/22) >/dev/null 2>&1 \
    && echo "It's up" || echo "It's down"
It's up

$ (echo > /dev/tcp/skinner/222) >/dev/null 2>&1 && \
    echo "It's up" || echo "It's down"
It's down

echo > /dev/...をこのように括弧で囲む必要があるのは、(echo > /dev/...)を使用しないと、接続テストが失敗した場合に、これらのタイプのメッセージが表示されるためです。

$ (echo > /dev/tcp/skinner/223) && echo hi
bash: connect: Connection refused
bash: /dev/tcp/skinner/223: Connection refused

これらはデバイス/dev/nullにデータを書き込もうとする試みから来ているので、単に/dev/tcpにリダイレクトすることはできません。そのため、そのすべての出力をサブコマンド、つまり(...cmds...)内にキャプチャし、サブコマンドの出力をリダイレクトします。

56
slm

私は、curltelnetと同様の方法で仕事を終わらせるかもしれないことを発見しました、そしてcurlはリスナーがどのプロトコルを期待するかさえあなたに言うでしょう。

curlの最初の引数として、ホスト名とポートからHTTP URIを構築します。 curlが接続できる場合は、プロトコルの不一致を報告して終了します(リスナーがWebサービスではない場合)。 curlが接続できない場合はタイムアウトします。

たとえば、ホスト10.0.0.99のポート5672が閉じられているか、ファイアウォールによってブロックされています。

$ curl http://10.0.0.99:5672
curl: (7) couldn't connect to Host

ただし、別のシステムからは、ホスト10.0.0.99上のポート5672に到達でき、AMQPリスナーを実行しているように見えます。

$ curl http://10.0.0.99:5672
curl: (56) Failure when receiving data from the peer
AMQP

異なるメッセージを区別することが重要です。最初の失敗はcurlがポートに接続できなかったためです。 curlはAMQPリスナーの代わりにHTTPリスナーを期待していましたが、2番目の失敗は成功テストです。

43
Steve HHH
[admin@automation-server 1.2.2]# nc -v -z -w2 192.168.193.173 6443
nc: connect to 192.168.193.173 port 6443 (tcp) failed: Connection refused

[admin@automation-server 1.2.2]# nc -v -z -w2 192.168.194.4 6443
Connection to 192.168.194.4 6443 port [tcp/Sun-sr-https] succeeded!

それがあなたの問題を解決することを願っています:)

これがワンライナーです。

</dev/tcp/localhost/11211 && echo Port is open || echo Port is closed

@ lornix answer で説明されているBash構文を使用する。

詳細については、 を参照してください。Advanced Bash-Scripting Guide:第29章/dev/proc

9
kenorb

これらの答えのどれも私のために働かないようだったので私は丸一日苦労していました。問題は、最新のncがもはや-zフラグを持っていないのに対し、TCPを介した直接アクセスは(@lornixと@slmによると)ホストがアクセスできない場合には失敗することです。私はやっと このページ を見つけました、そこで私はついに1つではなく2つの実用例を見つけました:

  1. nc -w1 127.0.0.1 22 </dev/null

    -wフラグはタイムアウトを処理し、</dev/null-zフラグを置き換えます)

  2. timeout 1 bash -c '(echo > /dev/tcp/127.0.0.1/22) >/dev/null 2>&1'

    timeoutコマンドはタイムアウトを処理し、残りは@slmからのものです)

次に、単に&&||(あるいは$?)を使って結果を抽出します。うまくいけば、誰かがこの情報が役に立つと思うでしょう。

6
Azukikuru

それはあなたの箱の上で利用可能であるべきではありませんが、nmapで試してください。

2
peperunas

参照用に、@ peperunasの回答を拡張します。

nmapを使用してテストする方法は次のとおりです。

nmap -p 22 127.0.0.1

(上記の例では、デモンストレーションのためにlocalhostを使用しています)

1
user138278

@kenorbと@Azukikuruの回答を組み合わせることで、ポートのオープン/クローズ/ファイアウォールをテストできます。

timeout 1 bash -c '</dev/tcp/127.0.0.1/22 && echo Port is open || echo Port is closed' || echo Connection timeout

任意のポートに到達するためのカールを使用した別のアプローチ

curl telnet://127.0.0.1:22
1
Miguel Ferreira

これはあなたのシステムに何がインストールされているかに応じて方法の一つを選ぶ関数です:

# Check_port <address> <port> 
check_port() {
if [ "$(which nc)" != "" ]; then 
    tool=nc
Elif [ "$(which curl)" != "" ]; then
     tool=curl
Elif [ "$(which telnet)" != "" ]; then
     tool=telnet
Elif [ -e /dev/tcp ]; then
      if [ "$(which gtimeout)" != "" ]; then  
       tool=gtimeout
      Elif [ "$(which timeout)" != "" ]; then  
       tool=timeout
      else
       tool=devtcp
      fi
fi
echo "Using $tool to test access to $1:$2"
case $tool in
nc) nc -v -G 5 -z -w2 $1 $2 ;;
curl) curl --connect-timeout 10 http://$1:$2 ;;
telnet) telnet $1 $2 ;;
gtimeout)  gtimeout 1 bash -c "</dev/tcp/${1}/${2} && echo Port is open || echo Port is closed" || echo Connection timeout ;;
timeout)  timeout 1 bash -c "</dev/tcp/${1}/${2} && echo Port is open || echo Port is closed" || echo Connection timeout ;;
devtcp)  </dev/tcp/${1}/${2} && echo Port is open || echo Port is closed ;;
*) echo "no tools available to test $1 port $2";;
esac

}
export check_port
1
Robert Boyd

システム以上のものをテストしたい場合は、私たちのテストツールdda-serverspec( https://github.com/DomainDrivenArchitecture/dda-serverspec-crate )そのようなタスクのために。あなたの期待を定義することができます

{:netcat [{:Host "mywebserver.com" :port "443"}
          {:Host "telnet mywebserver.com" :port "80"}
          {:Host "telnet mywebserver.com" :port "8443"}]}

そして、これらの期待値をlocalhostまたはremote hostsに対してテストします(sshで接続します)。リモートテストの場合は、ターゲットを定義します。

{:existing [{:node-name "test-vm1"
             :node-ip "35.157.19.218"}
            {:node-name "test-vm2"
             :node-ip "18.194.113.138"}]
 :provisioning-user {:login "ubuntu"}}

Java -jar dda-serverspec.jar --targets targets.edn serverspec.ednでテストを実行することができます

フードの下で我々は上で処理されたようにnetcatを使っています...

0
jerger