IPアドレスの確認(IPv4およびIPv6)

IPアドレスの確認(IPv4およびIPv6)

簡単に言えば、Bashスクリプトの文字列が有効なIPアドレスを表すことを確認したいと思います。私は他の多くの人のように正規表現を使ってこれを実行しようとするトラップに陥ったと思います。これはIPv4には十分でしたが、IPv6はより複雑で(ゼロ圧縮をサポートするため)、複雑で特に読みにくいソリューションです。 。

しかし、UnixとLinuxはIPアドレスを明確に理解しているので、bashでIPアドレスをチェックするより良い方法があるかどうか疑問に思います。これを行うために使用できるかなり一般的なツールを使用することをお勧めします。

filter_var実際にはPHP関数を使用する現在のソリューションを置き換えたいので、他の言語(Pythonなど)を使用したくありません。動作しますが、正規表現と同様に、1つでは使用したくない2番目の言語を紹介します。

0.0.0.0-255.255.255.255最後に、IPアドレス範囲(例えば、など)も処理するソリューションがあれば理想的でしょうが0.0.0.0/16、これを直接処理することはできます。

答え1

ipコマンドを使うのはどうですか?

ip route get <ip-address>

無効な場合、戻り値は 1 です。

(2022/9/17)@MaXi32さんのコメントに返信するために、インターネット接続なしで私のLinuxノートブックですばやく確認してみました。ネットワークが閉じると、ip コマンドは無効な IP に対して 1 を返し、有効な IP に対して 2 を返します。

有効なIPの場合:

$ ip route get 192.168.0.255 ; echo $?
RTNETLINK answers: Network is unreachable
2
$ ip route get fd00::192.168.0.255 ; echo $?
RTNETLINK answers: Network is unreachable
2

無効なIPの場合:

$ ip route get 192.168.0.256 ; echo $?
Error: any valid prefix is expected rather than "192.168.0.256".
1
$ ip route get fd00::192.168.0.256 ; echo $?
Error: any valid prefix is expected rather than "fd00::192.168.0.256".
1

IPコマンドバージョン:

$ ip -V
ip utility, iproute2-5.9.0, libbpf 0.3.0

(2022/9/17#2)inet_ptonを使って小さなプログラムを書くことができます。私はこれが良いと思います。次のコードは例から得られます。inet_pton マンページIPをテキストからバイナリに変換しようとし、IPが無効な場合はエラーが発生します。

   #include <arpa/inet.h>
   #include <stdio.h>
   #include <stdlib.h>
   #include <string.h>

   int
   main(int argc, char *argv[])
   {
       unsigned char buf[sizeof(struct in6_addr)];
       int domain, s;
       char str[INET6_ADDRSTRLEN];

       if (argc != 3) {
           fprintf(stderr, "Usage: %s {i4|i6|<num>} string\n", argv[0]);
           exit(EXIT_FAILURE);
       }

       domain = (strcmp(argv[1], "i4") == 0) ? AF_INET :
                (strcmp(argv[1], "i6") == 0) ? AF_INET6 : atoi(argv[1]);

       s = inet_pton(domain, argv[2], buf);
       if (s <= 0) {
           if (s == 0)
               fprintf(stderr, "Not in presentation format");
           else
               perror("inet_pton");
           exit(EXIT_FAILURE);
       }

       if (inet_ntop(domain, buf, str, INET6_ADDRSTRLEN) == NULL) {
           perror("inet_ntop");
           exit(EXIT_FAILURE);
       }

       printf("%s\n", str);

       exit(EXIT_SUCCESS);
   }

答え2

bash関連するシステムコールへの直接アクセスが不足している可能性があるため、同様の操作をinet_pton(3)実行するコールが必要になる場合がありますsipcalc(さまざまなUNIXのポートまたはパッケージツリーに存在する必要があります)。より高いレベルの言語も呼び出しを受けることができますが、inet_pton(3)詳細は言語によって異なります。NetAddr::IPPerlのサブネット関連コード。

答え3

@ktakaの答えによると、ip route getスクリプトがネットワーク接続に大きく依存しない限り、IPアドレスを確認するために使用しないことをお勧めします。これは、システムのインターネット接続が良好でない場合、またはインターネット接続が完全に切断された場合ip route getにIPが正しく定義されていても、スクリプトを使用すると常にエラーコード(0以外)を返すためです。

解決策:

@Rolf Randerが提供した手動リンクを見つけましたが、なぜipcalcDebian 11のバイナリにそのオプションがなく、-c以前のipcalcバイナリもそれをサポートしていないのか混乱していたので、マニュアルipv6でこのキーワードを使用してGoogleを検索しました。作成者のユーザー名ページから取得し、dcantrell ipcalc公式リンクはここから取得します。

https://gitlab.com/ipcalc/ipcalc

上記のアドレスは、ipcalcIPv4とIPv6の両方を正式にサポートするIPアドレスです。インストールするには、mesonを含む最新のビルドを使用することをお勧めします(ただし、me​​sonを使用したくない場合は、以前のmakeビルドも提供します)。

だから私が設定したipcalc方法は次のとおりですDebian 11

既存のipcalcを削除する(既存のバージョンが悪い)

apt-get -y remove ipcalc
rm -rf "/usr/bin/ipcalc"

次に、公式リポジトリからipcalcをインストールします。

apt -y install meson
git clone https://gitlab.com/ipcalc/ipcalc.git
cd ipcalc
meson setup build --buildtype=release
ninja -C build
cp build/ipcalc /usr/bin
apt -y remove meson

ipcalc --version

1.0.1

これでipcalcIPv4とIPv6を確認できます。

#!/bin/bash
IP="1.1.1.1"
if ipcalc -s -c $IP; then
  echo "valid IPv4 or IPv6"
else
  echo "Invalid IPv4 or Ipv6"
fi

-sエラーメッセージを無視し-cて出力せずに確認

特定のIPv4を確認するには、Check IPv6を使用または-4使用します-6。例:

#!/bin/bash

# IP is a valid IPv6
IP="::1"

# But we want to check only IPv4

if ipcalc -s -4 -c $IP; then
  echo "valid IPv4"
else
  echo "Invalid IPv4"
fi

出力:

Invalid IPv4

私はずっと前からAndroidを使用してきましたsipcalcが、IPv4とIPv6の両方のチェックを実行していますが、ほとんどの出力が単純で他の目的のためのjson出力があるのでAndroidを好みます。ipv6calcipcalc

編集する

(2022年10月23日):

@ktakaの最新のコメントに基づいた主なポイントは、ip route getインターネットに接続せずに使用するときに次のようなことです。

$ ip route get 192.168.0.255 ; echo $?
RTNETLINK answers: Network is unreachable
2

システムがファイアウォールの背後にある場合、または接続状態が悪い場合、有効なIPは返されません。 IPは有効で、ネットワークに接続できないなど、不要な情報を知らせるのではなく、成功コード0を返す必要があります。

答え4

これはipv4の問題を解決することができます

# check IPv4 syntax
if [[ "$ip" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
    echo 'Valid IP'
else
    echo "Invalid IP: $ip" >&2
    exit 1
fi

私は私がインポートしたスクリプトにipv6を実装していますが、完了したらこの投稿を更新します。

関連情報