昔は、リモートホスト上のポートが開いているかどうかを確認するためにtelnet
を使用しました。telnet hostname port
は、任意のホスト上の任意のポートに接続しようとし、生のTCPストリームにアクセスできるようにします。
最近では、私が取り組んでいるシステムにはtelnetがインストールされておらず(セキュリティ上の理由から)、すべてのホストへのすべてのアウトバウンド接続はデフォルトでブロックされています。時間の経過とともに、どのポートがどのホストに対して開かれているのかがわからなくなります。
リモートシステムのポートが開いているかどうかをテストする別の方法はありますか - インストールされているパッケージの数が限られているLinuxシステムを使用していて、telnet
が使用できないのですか?
Bashは TCP と UDP のポートにアクセスすることができました。しばらくの間。 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
タアダ!
素晴らしく冗長です。 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
Netcatは便利なツールです。
nc 127.0.0.1 123 &> /dev/null; echo $?
ポート123が開いていれば0
を、閉じていれば1
を出力します。
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...)
内にキャプチャし、サブコマンドの出力をリダイレクトします。
私は、curl
がtelnet
と同様の方法で仕事を終わらせるかもしれないことを発見しました、そして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番目の失敗は成功テストです。
[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
。
これらの答えのどれも私のために働かないようだったので私は丸一日苦労していました。問題は、最新のnc
がもはや-z
フラグを持っていないのに対し、TCPを介した直接アクセスは(@lornixと@slmによると)ホストがアクセスできない場合には失敗することです。私はやっと このページ を見つけました、そこで私はついに1つではなく2つの実用例を見つけました:
nc -w1 127.0.0.1 22 </dev/null
(-w
フラグはタイムアウトを処理し、</dev/null
は-z
フラグを置き換えます)
timeout 1 bash -c '(echo > /dev/tcp/127.0.0.1/22) >/dev/null 2>&1'
(timeout
コマンドはタイムアウトを処理し、残りは@slmからのものです)
次に、単に&&
や||
(あるいは$?
)を使って結果を抽出します。うまくいけば、誰かがこの情報が役に立つと思うでしょう。
それはあなたの箱の上で利用可能であるべきではありませんが、nmap
で試してください。
参照用に、@ peperunasの回答を拡張します。
nmapを使用してテストする方法は次のとおりです。
nmap -p 22 127.0.0.1
(上記の例では、デモンストレーションのためにlocalhostを使用しています)
@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
これはあなたのシステムに何がインストールされているかに応じて方法の一つを選ぶ関数です:
# 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
システム以上のものをテストしたい場合は、私たちのテストツール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を使っています...