Python 으로 네트워크 인터페이스 설정 방법

PythonBeginner
지금 연습하기

소개

Python 은 네트워크 인터페이스 작업을 위한 강력한 기능을 제공하여, 개발자가 프로그래밍 방식으로 네트워크 정보를 검색하고 네트워크 설정을 구성할 수 있도록 합니다. 이러한 실용적인 기술은 네트워크 관리자, 시스템 엔지니어, 그리고 네트워크 관련 애플리케이션을 개발하는 개발자에게 매우 유용합니다.

이 Lab 에서는 Python 을 사용하여 Linux 시스템에서 네트워크 인터페이스를 검사하고 관리하는 방법을 배우게 됩니다. 기본적인 인터페이스 식별부터 시작하여, 상세한 네트워크 정보 검색, 그리고 네트워크 트래픽 모니터링으로 진행할 것입니다. 이 Lab 을 마치면 Python 의 네트워킹 라이브러리에 대한 실질적인 경험을 얻게 되며, 이러한 기술을 실제 네트워킹 작업에 적용할 수 있게 될 것입니다.

필요한 Python 패키지 설치

Python 에서 네트워크 인터페이스 작업을 시작하기 전에, 필요한 패키지를 설치해야 합니다. 우리가 사용할 두 가지 주요 패키지는 다음과 같습니다.

  • netifaces: 네트워크 인터페이스 정보를 검색하기 위한 크로스 플랫폼 라이브러리
  • psutil: 네트워크 통계를 포함한 시스템 정보를 검색하기 위한 라이브러리

pip 를 사용하여 이러한 패키지를 설치해 보겠습니다.

패키지 설치

터미널을 열고 다음 명령을 실행하여 필요한 패키지를 설치합니다.

pip install netifaces psutil

패키지가 다운로드 및 설치되는 것을 나타내는 출력을 볼 수 있습니다. 설치가 완료될 때까지 기다린 후 다음 단계로 진행하십시오.

설치 확인

간단한 Python 스크립트를 생성하여 패키지가 올바르게 설치되었는지 확인해 보겠습니다. VSCode 편집기에서 check_packages.py라는 새 파일을 만듭니다.

  1. 왼쪽 사이드바에서 "Explorer" 아이콘을 클릭합니다 (또는 Ctrl+E 를 누릅니다).
  2. "New File" 버튼을 클릭합니다.
  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 를 누르거나 메뉴에서 "File > Save"를 선택하여 파일을 저장합니다.

이제 터미널을 열고 (아직 열려 있지 않은 경우) 다음을 실행하여 스크립트를 실행합니다.

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. 아직 열려 있지 않은 경우 왼쪽 사이드바에서 "Explorer" 아이콘을 클릭합니다.
  2. "New File" 버튼을 클릭합니다.
  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: 기본 이더넷 인터페이스
  • wlan0: 기본 무선 인터페이스 (사용 가능한 경우)
  • docker0: Docker 브리지 네트워크 인터페이스 (Docker 가 설치된 경우)

네트워크 인터페이스 이름 이해

네트워크 인터페이스 이름은 운영 체제 및 구성에 따라 다를 수 있습니다.

  • 기존 Linux 시스템에서는 이더넷의 경우 인터페이스가 eth0, eth1 등으로 명명됩니다.
  • 예측 가능한 네트워크 인터페이스 이름을 사용하는 최신 시스템에서는 enp0s3 또는 ens33과 같은 이름을 볼 수 있습니다.
  • 가상 인터페이스는 브리지의 경우 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. Explorer 창에서 "New File" 버튼을 클릭합니다.
  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. Explorer 창에서 "New File" 버튼을 클릭합니다.
  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 번의 반복 동안 매 초마다 업데이트됩니다.

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

두 번째 명령줄 인수로 반복 횟수를 지정할 수도 있습니다.

python3 monitor_traffic.py eth0 5

이렇게 하면 기본값인 10 번 대신 5 번의 반복 동안 트래픽을 모니터링합니다.

일부 네트워크 트래픽 생성

실제 트래픽으로 모니터링 스크립트가 작동하는 것을 보려면 두 번째 터미널을 열고 일부 네트워크 트래픽을 생성할 수 있습니다. 이를 수행하는 간단한 스크립트를 만들어 보겠습니다.

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

이제 한 터미널에서 모니터링 스크립트를 실행합니다.

python3 monitor_traffic.py eth0 15

그리고 별도의 터미널에서 트래픽 생성 스크립트를 실행합니다.

python3 generate_traffic.py

이제 트래픽 생성 스크립트가 HTTP 요청을 할 때 모니터링 스크립트에서 캡처한 네트워크 활동을 볼 수 있습니다.

이 연습은 Python 을 사용하여 네트워크 문제 진단, 대역폭 사용량 모니터링 및 네트워크 트래픽 패턴 이해에 유용한 실시간으로 네트워크 인터페이스 활동을 모니터링하는 방법을 보여줍니다.

요약

이 Lab 에서는 Python 의 네트워크 인터페이스 관리 기능에 대한 실질적인 경험을 얻었습니다. 수행한 작업은 다음과 같습니다.

  1. 환경 설정: 네트워크 인터페이스 작업을 위해 필요한 Python 패키지 (netifacespsutil) 를 설치하고 구성했습니다.

  2. 네트워크 인터페이스 나열: 시스템에서 사용 가능한 모든 네트워크 인터페이스를 식별하고 이에 대한 기본 정보를 표시하는 스크립트를 만들었습니다.

  3. 상세 인터페이스 정보 검색: IP 주소, MAC 주소 및 게이트웨이 정보를 포함하여 네트워크 인터페이스에서 상세한 구성 정보를 추출하는 포괄적인 스크립트를 작성했습니다.

  4. 네트워크 트래픽 모니터링: 특정 인터페이스를 통해 송수신되는 데이터를 추적하는 실시간 네트워크 트래픽 모니터링 도구를 구현했습니다.

이러한 기술은 다음과 같은 Python 에서 더 발전된 네트워크 관리 작업의 기반을 형성합니다.

  • 네트워크 구성 변경 자동화
  • 네트워크 모니터링 대시보드 구축
  • 네트워크 진단 도구 생성
  • 네트워크 보안 애플리케이션 개발

프로그래밍 방식으로 네트워크 인터페이스와 상호 작용하는 방법을 이해함으로써 이제 특정 요구 사항에 맞게 사용자 정의 네트워킹 도구를 구축할 수 있습니다. 이 지식은 시스템 관리자, 네트워크 엔지니어 및 네트워크 애플리케이션을 작업하는 개발자에게 특히 유용합니다.