Python でのネットワークインターフェース設定方法

PythonBeginner
オンラインで実践に進む

はじめに

Python は、ネットワークインターフェースを操作するための強力な機能を提供しており、開発者はプログラム的にネットワーク情報を取得し、ネットワーク設定を構成することができます。この実践的なスキルは、ネットワーク管理者、システムエンジニア、およびネットワーク関連アプリケーションに取り組む開発者にとって貴重です。

この実験(Lab)では、Python を使用して Linux システム上のネットワークインターフェースを検査および管理する方法を学びます。基本的なインターフェースの識別から始め、詳細なネットワーク情報の取得に進み、最後にネットワークトラフィックの監視を行います。この実験(Lab)の終わりには、Python のネットワーキングライブラリに関する実践的な経験を得て、これらのスキルを実際のネットワーキングタスクに適用できるようになります。

必要な Python パッケージのインストール

Python でネットワークインターフェースを操作する前に、必要なパッケージをインストールする必要があります。使用する主なパッケージは次の 2 つです。

  • netifaces: ネットワークインターフェース情報を取得するためのクロスプラットフォームライブラリ
  • psutil: ネットワーク統計など、システム情報を取得するためのライブラリ

pip を使用してこれらのパッケージをインストールすることから始めましょう。

パッケージのインストール

ターミナルを開き、次のコマンドを実行して必要なパッケージをインストールします。

pip install netifaces psutil

パッケージがダウンロードされ、インストールされていることを示す出力が表示されるはずです。インストールが完了するまで待ってから、続行してください。

インストールの検証

簡単な Python スクリプトを作成して、パッケージが正しくインストールされたことを確認しましょう。VSCode エディターで check_packages.py という新しいファイルを作成します。

  1. 左側のサイドバーの「エクスプローラー」アイコンをクリックします(または Ctrl+E を押します)。
  2. 「新しいファイル」ボタンをクリックします。
  3. ファイル名を check_packages.py とします。
  4. ファイルに次のコードを追加します。
try:
    import netifaces
    import psutil
    print("Both packages installed successfully!")
    print(f"netifaces version: {netifaces.__version__}")
    print(f"psutil version: {psutil.__version__}")
except ImportError as e:
    print(f"Error importing packages: {e}")

Ctrl+S を押すか、メニューから「ファイル > 保存」を選択してファイルを保存します。

次に、ターミナルを開き(まだ開いていない場合)、以下を実行してスクリプトを実行します。

python3 check_packages.py

次のような出力が表示されるはずです。

Both packages installed successfully!
netifaces version: 0.11.0
psutil version: 5.9.0

正確なバージョン番号は異なる場合がありますが、「installed successfully」メッセージが表示されれば、次のステップに進む準備ができています。

ネットワークインターフェースのリスト表示

必要なパッケージがインストールされたので、ネットワークインターフェースの探索を開始しましょう。最初のステップは、システム上で利用可能なすべてのネットワークインターフェースを特定することです。

ネットワークインターフェースをリスト表示するスクリプトの作成

VSCode エディターで list_interfaces.py という名前の新しいファイルを作成します。

  1. まだ開いていない場合は、左側のサイドバーの「エクスプローラー」アイコンをクリックします。
  2. 「新しいファイル」ボタンをクリックします。
  3. ファイル名を list_interfaces.py とします。
  4. 次のコードを追加します。
import netifaces

def list_network_interfaces():
    """List all network interfaces available on the system."""
    interfaces = netifaces.interfaces()

    print("Available network interfaces:")
    for index, interface in enumerate(interfaces, 1):
        print(f"{index}. {interface}")

if __name__ == "__main__":
    list_network_interfaces()

Ctrl+S を押してファイルを保存します。

スクリプトの実行

次に、スクリプトを実行して、システム上のネットワークインターフェースのリストを表示します。

python3 list_interfaces.py

次のような出力が表示されるはずです。

Available network interfaces:
1. lo
2. eth0
3. docker0

正確なリストは、システム構成によって異なります。これらのインターフェースが通常何を表しているのかを理解しましょう。

  • lo: ループバックインターフェース(localhost)
  • eth0: プライマリ Ethernet インターフェース
  • wlan0: プライマリワイヤレスインターフェース(利用可能な場合)
  • docker0: Docker ブリッジネットワークインターフェース(Docker がインストールされている場合)

ネットワークインターフェース名の理解

ネットワークインターフェース名は、オペレーティングシステムと構成によって異なる場合があります。

  • 従来の Linux システムでは、インターフェースは Ethernet 用に eth0eth1 などの名前が付けられます。
  • 予測可能なネットワークインターフェース名を使用する新しいシステムでは、enp0s3ens33 などの名前が表示される場合があります。
  • 仮想インターフェースには、ブリッジ用の veth...br0 などの名前が付いている場合があります。

各インターフェースの詳細を提供するようにスクリプトを変更しましょう。 list_interfaces.py ファイルを次のコードで更新します。

import netifaces

def list_network_interfaces():
    """List all network interfaces available on the system with details."""
    interfaces = netifaces.interfaces()

    print("Available network interfaces:")
    for index, interface in enumerate(interfaces, 1):
        print(f"{index}. {interface}")

        ## Try to get addresses for this interface
        try:
            if netifaces.AF_INET in netifaces.ifaddresses(interface):
                ip_info = netifaces.ifaddresses(interface)[netifaces.AF_INET][0]
                print(f"   IPv4 Address: {ip_info.get('addr', 'None')}")
        except ValueError:
            print("   No IPv4 address assigned")

if __name__ == "__main__":
    list_network_interfaces()

ファイルを保存して、もう一度実行します。

python3 list_interfaces.py

これで、各インターフェースの IPv4 アドレスを含む、より詳細な出力が表示されるはずです。

Available network interfaces:
1. lo
   IPv4 Address: 127.0.0.1
2. eth0
   IPv4 Address: 172.17.0.2
3. docker0
   IPv4 Address: 172.17.0.1

これにより、システムで利用可能なネットワークインターフェースとその現在の IP アドレスをよりよく理解できます。

詳細なネットワークインターフェース情報の取得

利用可能なネットワークインターフェースをリスト表示できるようになったので、特定のネットワークインターフェースに関する詳細情報を取得するための、より包括的なスクリプトを作成しましょう。

ネットワークインターフェースの詳細スクリプトの作成

VSCode エディターで interface_details.py という名前の新しいファイルを作成します。

  1. エクスプローラーペインで「新しいファイル」ボタンをクリックします。
  2. ファイル名を interface_details.py とします。
  3. 次のコードを追加します。
import netifaces
import sys

def get_interface_details(interface_name):
    """
    Retrieve detailed information about a specific network interface.

    Args:
        interface_name (str): The name of the network interface

    Returns:
        None: Prints interface details to console
    """
    ## Check if the interface exists
    interfaces = netifaces.interfaces()
    if interface_name not in interfaces:
        print(f"Error: Interface '{interface_name}' does not exist.")
        print(f"Available interfaces: {', '.join(interfaces)}")
        return

    print(f"\nDetails for interface '{interface_name}':")
    print("-" * 50)

    ## Get addresses for all protocol families
    try:
        addresses = netifaces.ifaddresses(interface_name)

        ## IPv4 addresses (AF_INET)
        if netifaces.AF_INET in addresses:
            ipv4_info = addresses[netifaces.AF_INET][0]
            print("IPv4 Information:")
            print(f"  Address: {ipv4_info.get('addr', 'Not available')}")
            print(f"  Netmask: {ipv4_info.get('netmask', 'Not available')}")
            print(f"  Broadcast: {ipv4_info.get('broadcast', 'Not available')}")
        else:
            print("IPv4 Information: Not available")

        ## IPv6 addresses (AF_INET6)
        if netifaces.AF_INET6 in addresses:
            ipv6_info = addresses[netifaces.AF_INET6][0]
            print("\nIPv6 Information:")
            print(f"  Address: {ipv6_info.get('addr', 'Not available')}")
            print(f"  Netmask: {ipv6_info.get('netmask', 'Not available')}")
            print(f"  Scope: {ipv6_info.get('scope', 'Not available')}")
        else:
            print("\nIPv6 Information: Not available")

        ## MAC address (AF_LINK)
        if netifaces.AF_LINK in addresses:
            link_info = addresses[netifaces.AF_LINK][0]
            print("\nMAC Address Information:")
            print(f"  Address: {link_info.get('addr', 'Not available')}")
            print(f"  Broadcast: {link_info.get('broadcast', 'Not available')}")
        else:
            print("\nMAC Address Information: Not available")

        ## Gateway information
        gateways = netifaces.gateways()
        print("\nGateway Information:")
        if 'default' in gateways and netifaces.AF_INET in gateways['default']:
            gw_addr, gw_interface = gateways['default'][netifaces.AF_INET]
            if gw_interface == interface_name:
                print(f"  Default Gateway: {gw_addr}")
            else:
                print("  No default gateway for this interface")
        else:
            print("  No default gateway information available")

    except Exception as e:
        print(f"Error retrieving interface details: {e}")

if __name__ == "__main__":
    ## If an interface name is provided as a command-line argument, use it
    ## Otherwise, use the first interface from the list (excluding 'lo')
    if len(sys.argv) > 1:
        interface_name = sys.argv[1]
    else:
        interfaces = [i for i in netifaces.interfaces() if i != 'lo']
        if interfaces:
            interface_name = interfaces[0]
            print(f"No interface specified, using {interface_name}")
        else:
            print("No network interfaces available")
            sys.exit(1)

    get_interface_details(interface_name)

Ctrl+S を押してファイルを保存します。

スクリプトの実行

次に、スクリプトを実行して、特定のネットワークインターフェースに関する詳細情報を表示します。

python3 interface_details.py eth0

必要に応じて、eth0 を前のステップで確認したインターフェースのいずれかに置き換えてください。

次のような出力が表示されるはずです。

Details for interface 'eth0':
--------------------------------------------------
IPv4 Information:
  Address: 172.17.0.2
  Netmask: 255.255.0.0
  Broadcast: 172.17.255.255

IPv6 Information: Not available

MAC Address Information:
  Address: 02:42:ac:11:00:02
  Broadcast: ff:ff:ff:ff:ff:ff

Gateway Information:
  Default Gateway: 172.17.0.1

インターフェース名を指定せずにスクリプトを実行することもできます。その場合、最初の非ループバックインターフェースが自動的に選択されます。

python3 interface_details.py

このスクリプトは、次のようなネットワークインターフェースの構成に関する包括的なビューを提供します。

  1. IPv4 アドレス、ネットマスク、ブロードキャストアドレス
  2. IPv6 アドレス(利用可能な場合)
  3. MAC アドレス
  4. デフォルトゲートウェイ情報

この詳細情報を理解することは、ネットワークのトラブルシューティングと構成に不可欠です。

netifaces モジュール定数の探索

netifaces モジュールは、さまざまなアドレスファミリーを表すために定数を使用します。これらの定数を理解するための簡単なスクリプトを作成しましょう。 netifaces_constants.py という名前の新しいファイルを作成します。

import netifaces

## Print all address family constants
print("Address Family Constants in netifaces module:")
print(f"AF_INET (IPv4): {netifaces.AF_INET}")
print(f"AF_INET6 (IPv6): {netifaces.AF_INET6}")
print(f"AF_LINK (MAC/Hardware): {netifaces.AF_LINK}")

## Additional constants that might be available
for name in dir(netifaces):
    if name.startswith('AF_'):
        print(f"{name}: {getattr(netifaces, name)}")

このスクリプトを保存して実行します。

python3 netifaces_constants.py

次のような出力が表示されるはずです。

Address Family Constants in netifaces module:
AF_INET (IPv4): 2
AF_INET6 (IPv6): 10
AF_LINK (MAC/Hardware): 17
AF_APPLETALK: 5
AF_INET: 2
AF_INET6: 10
AF_IPX: 4
AF_LINK: 17
AF_UNIX: 1

これらの定数は、netifaces モジュールでさまざまな種類のネットワークアドレスを識別するために使用されます。それらを理解することは、モジュールの関数を操作する際に役立ちます。

ネットワークインターフェーストラフィックの監視

ネットワークインターフェース情報を取得する方法を理解したので、さらに一歩進んで、ネットワークトラフィックをリアルタイムで監視するスクリプトを作成しましょう。これにより、特定のインターフェースを通じて送受信されているデータの量を確認できます。

ネットワークトラフィック監視スクリプトの作成

VSCode エディターで monitor_traffic.py という名前の新しいファイルを作成します。

  1. エクスプローラーペインで「新しいファイル」ボタンをクリックします。
  2. ファイル名を monitor_traffic.py とします。
  3. 次のコードを追加します。
import psutil
import time
import sys
import netifaces

def bytes_to_readable(bytes_count):
    """Convert bytes to a human-readable format (KB, MB, GB)"""
    units = ['B', 'KB', 'MB', 'GB', 'TB']
    unit_index = 0
    converted_value = float(bytes_count)

    while converted_value >= 1024 and unit_index < len(units) - 1:
        converted_value /= 1024
        unit_index += 1

    return f"{converted_value:.2f} {units[unit_index]}"

def monitor_network_traffic(interface_name, interval=1, iterations=10):
    """
    Monitor network traffic on a specific interface for a given number of iterations.

    Args:
        interface_name (str): Name of the network interface to monitor
        interval (int): Time interval between measurements in seconds
        iterations (int): Number of measurements to take
    """
    ## Verify interface exists
    if interface_name not in netifaces.interfaces():
        print(f"Error: Interface '{interface_name}' does not exist.")
        print(f"Available interfaces: {', '.join(netifaces.interfaces())}")
        return

    print(f"Monitoring network traffic on {interface_name} (Ctrl+C to stop)")
    print("-" * 80)
    print(f"{'Time':<12} {'Bytes Sent':<15} {'Bytes Received':<15} {'Packets Sent':<15} {'Packets Received':<15}")
    print("-" * 80)

    try:
        ## Get initial stats
        net_io_counters = psutil.net_io_counters(pernic=True)
        if interface_name not in net_io_counters:
            print(f"Error: Cannot get stats for interface '{interface_name}'")
            return

        prev_stats = net_io_counters[interface_name]
        prev_bytes_sent = prev_stats.bytes_sent
        prev_bytes_recv = prev_stats.bytes_recv
        prev_packets_sent = prev_stats.packets_sent
        prev_packets_recv = prev_stats.packets_recv

        ## Monitor for the specified number of iterations
        for i in range(iterations):
            ## Wait for the specified interval
            time.sleep(interval)

            ## Get new stats
            net_io_counters = psutil.net_io_counters(pernic=True)
            new_stats = net_io_counters[interface_name]

            ## Calculate differences
            bytes_sent_diff = new_stats.bytes_sent - prev_bytes_sent
            bytes_recv_diff = new_stats.bytes_recv - prev_bytes_recv
            packets_sent_diff = new_stats.packets_sent - prev_packets_sent
            packets_recv_diff = new_stats.packets_recv - prev_packets_recv

            ## Update previous values
            prev_bytes_sent = new_stats.bytes_sent
            prev_bytes_recv = new_stats.bytes_recv
            prev_packets_sent = new_stats.packets_sent
            prev_packets_recv = new_stats.packets_recv

            ## Print the current stats
            current_time = time.strftime("%H:%M:%S")
            print(f"{current_time:<12} {bytes_to_readable(bytes_sent_diff):<15} "
                  f"{bytes_to_readable(bytes_recv_diff):<15} {packets_sent_diff:<15} "
                  f"{packets_recv_diff:<15}")

    except KeyboardInterrupt:
        print("\nMonitoring stopped by user")
    except Exception as e:
        print(f"Error during monitoring: {e}")

    print("\nTraffic summary for this session:")
    print(f"Total monitored time: {iterations * interval} seconds")

if __name__ == "__main__":
    ## Get the interface name from command line arguments or use a default
    if len(sys.argv) > 1:
        interface_name = sys.argv[1]
    else:
        ## Try to find a non-loopback interface
        interfaces = [i for i in netifaces.interfaces() if i != 'lo']
        if interfaces:
            interface_name = interfaces[0]
            print(f"No interface specified, using {interface_name}")
        else:
            print("No network interfaces available")
            sys.exit(1)

    ## Get number of iterations from command line (default: 10)
    iterations = 10
    if len(sys.argv) > 2:
        try:
            iterations = int(sys.argv[2])
        except ValueError:
            print(f"Invalid iterations value: {sys.argv[2]}. Using default: 10")

    ## Monitor the network traffic
    monitor_network_traffic(interface_name, iterations=iterations)

Ctrl+S を押してファイルを保存します。

トラフィック監視スクリプトの実行

次に、スクリプトを実行して、特定のインターフェースのネットワークトラフィックを監視します。

python3 monitor_traffic.py eth0

必要に応じて、eth0 をシステム上の適切なインターフェース名に置き換えてください。

スクリプトは、ネットワークインターフェースを介して送受信されたデータの量を示す表を表示し、10 回の反復処理で 1 秒ごとに更新します。

Monitoring network traffic on eth0 (Ctrl+C to stop)
--------------------------------------------------------------------------------
Time         Bytes Sent      Bytes Received  Packets Sent    Packets Received
--------------------------------------------------------------------------------
14:25:30     0.00 B          156.00 B        0               2
14:25:31     0.00 B          0.00 B          0               0
14:25:32     0.00 B          0.00 B          0               0
14:25:33     456.00 B        1.24 KB         3               5
14:25:34     0.00 B          0.00 B          0               0
14:25:35     0.00 B          0.00 B          0               0
14:25:36     66.00 B         102.00 B        1               1
14:25:37     0.00 B          0.00 B          0               0
14:25:38     0.00 B          0.00 B          0               0
14:25:39     0.00 B          0.00 B          0               0

Traffic summary for this session:
Total monitored time: 10 seconds

2 番目のコマンドライン引数として、反復回数を指定することもできます。

python3 monitor_traffic.py eth0 5

これにより、デフォルトの 10 回ではなく、5 回の反復処理でトラフィックが監視されます。

ネットワークトラフィックの生成

実際のトラフィックで監視スクリプトを動作させるには、2 番目のターミナルを開き、いくつかのネットワークトラフィックを生成できます。これを行うための簡単なスクリプトを作成しましょう。

generate_traffic.py という名前の新しいファイルを作成します。

import requests
import time
import sys

def generate_traffic(iterations=5, delay=1):
    """Generate some network traffic by making HTTP requests"""
    print(f"Generating network traffic over {iterations} iterations...")

    for i in range(iterations):
        try:
            ## Make a GET request to a public API
            response = requests.get("https://httpbin.org/get")
            print(f"Request {i+1}/{iterations}: Status {response.status_code}, "
                  f"Size {len(response.content)} bytes")

            ## Wait before the next request
            if i < iterations - 1:
                time.sleep(delay)

        except Exception as e:
            print(f"Error making request: {e}")

    print("Traffic generation complete")

if __name__ == "__main__":
    ## Get number of iterations from command line (default: 5)
    iterations = 5
    if len(sys.argv) > 1:
        try:
            iterations = int(sys.argv[1])
        except ValueError:
            print(f"Invalid iterations value: {sys.argv[1]}. Using default: 5")

    generate_traffic(iterations)

まず、requests ライブラリをインストールする必要があります。

pip install requests

次に、1 つのターミナルで監視スクリプトを実行します。

python3 monitor_traffic.py eth0 15

そして、別のターミナルでトラフィック生成スクリプトを実行します。

python3 generate_traffic.py

これで、トラフィック生成スクリプトが HTTP リクエストを行うと、監視スクリプトによってキャプチャされたネットワークアクティビティが表示されるはずです。

この演習では、Python を使用してネットワークインターフェースのアクティビティをリアルタイムで監視する方法を示しています。これは、ネットワークの問題の診断、帯域幅の使用状況の監視、およびネットワークトラフィックパターンの理解に役立ちます。

まとめ

この実験では、Python のネットワークインターフェース管理機能に関する実践的な経験を積みました。以下が達成した内容です。

  1. 環境のセットアップ: ネットワークインターフェースを操作するために必要な Python パッケージ (netifaces および psutil) をインストールし、設定しました。

  2. ネットワークインターフェースのリスト表示: システム上のすべての利用可能なネットワークインターフェースを識別し、それらに関する基本情報を表示するスクリプトを作成しました。

  3. 詳細なインターフェース情報の取得: IP アドレス、MAC アドレス、ゲートウェイ情報など、ネットワークインターフェースから詳細な構成情報を抽出する包括的なスクリプトを作成しました。

  4. ネットワークトラフィックの監視: 特定のインターフェースを介して送受信されるデータを追跡する、リアルタイムのネットワークトラフィック監視ツールを実装しました。

これらのスキルは、次のような、より高度な Python でのネットワーク管理タスクの基礎となります。

  • ネットワーク構成の変更の自動化
  • ネットワーク監視ダッシュボードの構築
  • ネットワーク診断ツールの作成
  • ネットワークセキュリティアプリケーションの開発

プログラム的にネットワークインターフェースと対話する方法を理解することにより、特定の要件に合わせてカスタマイズされたネットワークツールを構築できるようになりました。この知識は、システム管理者、ネットワークエンジニア、およびネットワークアプリケーションを開発している開発者にとって特に価値があります。