linux python pyroute 2将WiFi接口移动到网络命名空间

jtw3ybtb  于 2023-11-17  发布在  Linux
关注(0)|答案(1)|浏览(147)

我想使用python pyroute 2在Linux上发现一个USB WiFi加密狗,并将其移动到一个网络名称空间中。
我可以用以太网接口做到这一点,但我明白,我必须使用物理层移动它与pyroute 2,如果它是一个wifi接口。我检查了文档,没有看到一个例子,如何做到这一点。
下面是我目前为止所做的。我如何使用pyroute 2将我的USB WiFi加密狗移动到网络命名空间?

# Inspect networking interfaces
import netifaces

# Setup netowrking namespaces
from pyroute2 import NetNS, NSPopen, netns, IPDB
from pyroute2 import IW
from pyroute2 import IPRoute
from pyroute2.netlink import NetlinkError

# Get a list of all the network interfaces
interfaces = netifaces.interfaces()

# Manage interfaces
ipdb = IPDB()

# Loop over all the interfaces and print their details
for iface in interfaces:
    iface_details = netifaces.ifaddresses(iface)
    if iface.find("wlxc") >= 0:

        print(f"Found USB Wi-Fi interface: {iface} with details: {iface_details}")

        # Truncate the long name
        truncated_name = iface[-8:-1]

        # Create a networking namespace
        ipdb_netns = IPDB(nl=NetNS(truncated_name))

        # Command to run
        program_command = ["ifconfig"]

        # Get the interface
        print(f"Truncated name is: {truncated_name}")
        link_iface = ipdb.interfaces[iface]
        print(f"Link interface: {link_iface} ...")

        # Look for the wireless index
        ip = IPRoute()
        iw = IW()
        index = ip.link_lookup(ifname=iface)[0]
        try:
            wifi_if = iw.get_interface_by_ifindex(index)
            print(f"Wireless interface: {wifi_if}")

            with ipdb.interfaces[iface] as if_to_move:
                print(f"Moving interface: {if_to_move} to: {truncated_name}")
                if_to_move.net_ns_fd = truncated_name
            print(f"Done moving to: {truncated_name} ...")
        except NetlinkError as e:
            if e.code == 19:  # 19 'No such device'
                print("not a wireless interface")
        finally:
            iw.close()
            ip.close()

字符串
错误代码:

Found USB Wi-Fi interface: wlxc87f548d9633 with details: {17: [{'addr': 'c8:7f:54:8d:96:33', 'broadcast': 'ff:ff:ff:ff:ff:ff'}]}
Truncated name is: 548d963
Link interface: {'address': 'c8:7f:54:8d:96:33', 'broadcast': 'ff:ff:ff:ff:ff:ff', 'ifname': 'wlxc87f548d9633', 'mtu': 1500, 'qdisc': 'noqueue', 'txqlen': 1000, 'operstate': 'DOWN', 'linkmode': 1, 'group': 0, 'promiscuity': 0, 'num_tx_queues': 1, 'num_rx_queues': 1, 'carrier': 0, 'carrier_changes': 1, 'proto_down': 0, 'gso_max_segs': 65535, 'gso_max_size': 65536, 'xdp': {'attrs': [('IFLA_XDP_ATTACHED', None)]}, 'carrier_up_count': 0, 'carrier_down_count': 1, 'min_mtu': 256, 'max_mtu': 2304, 'perm_address': 'c8:7f:54:8d:96:33', 'parent_dev_name': '3-3:1.0', 'parent_dev_bus_name': 'usb', 'index': 10, 'flags': 4099, 'ipdb_scope': 'system', 'ipdb_priority': 0, 'vlans': (), 'ipaddr': (), 'ports': (), 'family': 0, 'ifi_type': 1, 'state': 'up', 'neighbours': ()} ...
Wireless interface: ({'cmd': 7, 'version': 1, 'reserved': 0, 'attrs': [('NL80211_ATTR_IFINDEX', 10), ('NL80211_ATTR_IFNAME', 'wlxc87f548d9633'), ('NL80211_ATTR_WIPHY', 1), ('NL80211_ATTR_IFTYPE', 2), ('NL80211_ATTR_WDEV', 4294967297), ('NL80211_ATTR_MAC', 'c8:7f:54:8d:96:33'), ('NL80211_ATTR_GENERATION', 17), ('NL80211_ATTR_4ADDR', '00'), ('NL80211_ATTR_WIPHY_TX_POWER_LEVEL', 1600), ('NL80211_ATTR_TXQ_STATS', '08:00:01:00:00:00:00:00:08:00:02:00:00:00:00:00:08:00:03:00:00:00:00:00:08:00:04:00:00:00:00:00:08:00:05:00:00:00:00:00:08:00:06:00:00:00:00:00:08:00:08:00:00:00:00:00:08:00:09:00:00:00:00:00:08:00:0a:00:00:00:00:00')], 'header': {'length': 188, 'type': 34, 'flags': 0, 'sequence_number': 255, 'pid': 14840, 'error': None, 'target': 'localhost', 'stats': Stats(qsize=0, delta=0, delay=0)}, 'event': 'NL80211_CMD_NEW_INTERFACE'},)
Moving interface: {'address': 'c8:7f:54:8d:96:33', 'broadcast': 'ff:ff:ff:ff:ff:ff', 'ifname': 'wlxc87f548d9633', 'mtu': 1500, 'qdisc': 'noqueue', 'txqlen': 1000, 'operstate': 'DOWN', 'linkmode': 1, 'group': 0, 'promiscuity': 0, 'num_tx_queues': 1, 'num_rx_queues': 1, 'carrier': 0, 'carrier_changes': 1, 'proto_down': 0, 'gso_max_segs': 65535, 'gso_max_size': 65536, 'xdp': {'attrs': [('IFLA_XDP_ATTACHED', None)]}, 'carrier_up_count': 0, 'carrier_down_count': 1, 'min_mtu': 256, 'max_mtu': 2304, 'perm_address': 'c8:7f:54:8d:96:33', 'parent_dev_name': '3-3:1.0', 'parent_dev_bus_name': 'usb', 'index': 10, 'flags': 4099, 'ipdb_scope': 'system', 'ipdb_priority': 0, 'vlans': (), 'ipaddr': (), 'ports': (), 'family': 0, 'ifi_type': 1, 'state': 'up', 'neighbours': ()} to: 548d963
fail <class 'NoneType'>
fail <class 'NoneType'>


更新了代码,并提供了建议的答案:

#!/usr/bin/python3

# Configure logging
import logging
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO, format="%(asctime)s:%(levelname)s:%(message)s")

# Inspect networking interfaces
import netifaces

# Setup netowrking namespaces
from pyroute2 import NetNS, NSPopen, netns, IPDB, IPRoute

# Get a list of all the network interfaces
interfaces = netifaces.interfaces()

# Managing network interfaces
with IPDB() as ipdb:

    # Loop over all the interfaces and logger.info their details
    for iface in interfaces:

        # Determine interface information
        iface_details = netifaces.ifaddresses(iface)
        if iface.find("wlxc") >= 0:

            logger.info(f"Found USB Wi-Fi interface: {iface} with details: {iface_details}")

            # Attempt to remove a networking namespace by the same name
            iface_truncate = iface[-4:]
            net_namespace = f"{iface_truncate}-ns"
            try:
                netns.remove(net_namespace)
            except Exception as err:
                logger.warning(f"Namespace does not exist and we could not remove it: {net_namespace} ...")

            # Create a new network namespace or identify an existing one
            logger.info(f"Trying to create network namespace: {net_namespace} ...")
            netns.create(net_namespace)

            # Get the interface index
            with IPRoute() as ip:
                index = ip.link_lookup(ifname=iface)[0]

            logger.info(f"Index of USB WiFi is: {index} ...")

            logger.info(f"Interfaces: {ipdb.interfaces[iface]} ...")

            # Move the interface to the new network namespace
            with ipdb.interfaces[index] as interf:
                interf.net_ns_fd = net_namespace
                logger.info(f"Moved {iface} to {net_namespace}")

            logger.info("Done moving interface ...")

# Close IPDB
ipdb.release()


Traceback最新代码:

2023-11-13 21:05:36,676:WARNING:Deprecation warning https://docs.pyroute2.org/ipdb_toc.html
2023-11-13 21:05:36,676:WARNING:To remove this DeprecationWarning exception, start IPDB(deprecation_warning=False, ...)
2023-11-13 21:05:36,678:INFO:Found USB Wi-Fi interface: wlxc87f548d9633 with details: {17: [{'addr': 'c8:7f:54:8d:96:33', 'broadcast': 'ff:ff:ff:ff:ff:ff'}]}
2023-11-13 21:05:36,680:INFO:Trying to create network namespace: 9633-ns ...
2023-11-13 21:05:36,686:INFO:Index of USB WiFi is: 10 ...
2023-11-13 21:05:36,700:INFO:Interfaces: {'address': 'c8:7f:54:8d:96:33', 'broadcast': 'ff:ff:ff:ff:ff:ff', 'ifname': 'wlxc87f548d9633', 'mtu': 1500, 'qdisc': 'noqueue', 'txqlen': 1000, 'operstate': 'DOWN', 'linkmode': 1, 'group': 0, 'promiscuity': 0, 'num_tx_queues': 1, 'num_rx_queues': 1, 'carrier': 0, 'carrier_changes': 1, 'proto_down': 0, 'gso_max_segs': 65535, 'gso_max_size': 65536, 'xdp': {'attrs': [('IFLA_XDP_ATTACHED', None)]}, 'carrier_up_count': 0, 'carrier_down_count': 1, 'min_mtu': 256, 'max_mtu': 2304, 'perm_address': 'c8:7f:54:8d:96:33', 'parent_dev_name': '3-3:1.0', 'parent_dev_bus_name': 'usb', 'index': 10, 'flags': 4099, 'ipdb_scope': 'system', 'ipdb_priority': 0, 'vlans': (), 'ipaddr': (), 'ports': (), 'family': 0, 'ifi_type': 1, 'state': 'up', 'neighbours': ()} ...
2023-11-13 21:05:36,700:INFO:Moved wlxc87f548d9633 to 9633-ns
fail <class 'NoneType'>
fail <class 'NoneType'>
Traceback (most recent call last):
  File "/home/user/Desktop/network-stress-test/network-stress-test.py", line 52, in <module>
    with ipdb.interfaces[index] as interf:
  File "/usr/local/lib/python3.10/dist-packages/pyroute2/ipdb/transactional.py", line 206, in __exit__
    self.commit()
  File "/usr/local/lib/python3.10/dist-packages/pyroute2/ipdb/interfaces.py", line 1136, in commit
    raise error
  File "/usr/local/lib/python3.10/dist-packages/pyroute2/ipdb/interfaces.py", line 1036, in commit
    run(nl.link, 'update', **request)
  File "/usr/local/lib/python3.10/dist-packages/pyroute2/ipdb/interfaces.py", line 515, in _run
    raise error
  File "/usr/local/lib/python3.10/dist-packages/pyroute2/ipdb/interfaces.py", line 510, in _run
    return cmd(*argv, **kwarg)
  File "/usr/local/lib/python3.10/dist-packages/pyroute2/iproute/linux.py", line 1672, in link
    ret = self.nlm_request(msg, msg_type=msg_type, msg_flags=msg_flags)
  File "/usr/local/lib/python3.10/dist-packages/pyroute2/netlink/nlsocket.py", line 870, in nlm_request
    return tuple(self._genlm_request(*argv, **kwarg))
  File "/usr/local/lib/python3.10/dist-packages/pyroute2/netlink/nlsocket.py", line 1214, in nlm_request
    for msg in self.get(
  File "/usr/local/lib/python3.10/dist-packages/pyroute2/netlink/nlsocket.py", line 873, in get
    return tuple(self._genlm_get(*argv, **kwarg))
  File "/usr/local/lib/python3.10/dist-packages/pyroute2/netlink/nlsocket.py", line 550, in get
    raise msg['header']['error']
pyroute2.netlink.exceptions.NetlinkError: (22, 'Invalid argument')

0ejtzxu1

0ejtzxu11#

您正在使用IPDB(nl=NetNS(truncated_name))创建新的网络名称空间,然后尝试使用with ipdb.interfaces[iface] as if_to_move:上下文管理器将接口移动到新名称空间,但似乎不起作用。
使用if_to_move.net_ns_fd = truncated_name,假设这会将接口移动到新的命名空间,可能适用于以太网接口。但是WiFi接口需要不同的处理,因为它们与无线PHY(物理层实体)相关联。
您应该首先使用它的ifname或索引来识别WiFi接口,您已经这样做了(例如,请参见“How to get interface names from kernel using pyroute2 IPDB function?“,但也可以参见IPRoute module)。
然后创建一个新的网络名称空间或标识一个现有的名称空间。并将WiFi接口移动到新的网络名称空间。

from pyroute2 import NetNS, IPDB, IW, IPRoute

# Get a list of all the network interfaces
interfaces = netifaces.interfaces()

# Create a new network namespace or identify an existing one
net_namespace = 'my_new_namespace'
netns.create(net_namespace)

# Managing network interfaces
with IPDB() as ipdb:
    for iface in interfaces:
        if iface.startswith("wl"):
            print(f"Found USB Wi-Fi interface: {iface}")
            
            # Get the interface index
            with IPRoute() as ip:
                index = ip.link_lookup(ifname=iface)[0]

            # Move the interface to the new network namespace
            with ipdb.interfaces[iface] as i:
                i.net_ns_fd = net_namespace
                print(f"Moved {iface} to {net_namespace}")

# Close IPDB
ipdb.release()

字符串
这应该会将您的USB WiFi加密狗移动到指定的网络名称空间。

[ Updated Setup ]
┌──────────────┐       ┌───────────────────┐
│ USB WiFi     ├──────►│ New Namespace     │
│ Dongle       │       │ (my_new_namespace)│
└──────────────┘       └───────────────────┘


我使用netns.create(net_namespace)来显式创建或标识命名空间,而不是将新的命名空间作为IPDB示例的一部分来创建。
然后,我使用with IPDB() as ipdb:来管理接口,使用with ipdb.interfaces[iface] as i:来处理要移动的接口(来自“将接口移动到名称空间”)。
使用您建议的代码,我从pyroute2: pyroute2.netlink.exceptions.NetlinkError: (22, 'Invalid argument')获得了一个Netlink追溯。
我在dmesg中未看到任何错误。
ip.link_lookup之后,我没有看到索引的任何用法,我也尝试过在那里使用索引。
在尝试将界面移至命名空间之后,会发生回溯。
更新后的代码中的NetlinkError: (22, 'Invalid argument')错误表明,在将接口移动到新的网络名称空间的操作过程中传递了无效的参数。
在您的代码中,您试图使用接口的索引with ipdb.interfaces[index] as interf:来移动接口。但是,Pyroute 2通常需要接口 name 而不是索引来执行此类操作。在将接口移动到名称空间时,请尝试使用接口名称而不是索引:

with ipdb.interfaces[iface] as interf:
    interf.net_ns_fd = net_namespace


那就是:

from pyroute2 import NetNS, IPDB, netns

# Your existing code for setting up logging and getting interfaces

with IPDB() as ipdb:
    for iface in interfaces:
        if iface.find("wlxc") >= 0:
            logger.info(f"Found USB Wi-Fi interface: {iface} with details: {iface_details}")

            # Your existing code for handling network namespace

            # Move the interface to the new network namespace
            try:
                with ipdb.interfaces[iface] as interf:
                    interf.down()  # Make sure the interface is down before moving
                    interf.net_ns_fd = net_namespace
                logger.info(f"Moved {iface} to {net_namespace}")
            except Exception as e:
                logger.error(f"Error moving interface: {e}")

            # Your code for further operations

# Your code for closing IPDB


此外,请确定您尝试将界面移至的命名空间存在且有效:在建立命名空间之后,请确认其存在,或更精确地行程与命名空间建立相关的潜在例外状况。

from pyroute2 import NetNS, IPDB, netns
import logging

# Configure logging
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO, format="%(asctime)s:%(levelname)s:%(message)s")

import netifaces

# Get a list of all the network interfaces
interfaces = netifaces.interfaces()

# Managing network interfaces
with IPDB() as ipdb:
    for iface in interfaces:
        if iface.find("wlxc") >= 0:
            iface_details = netifaces.ifaddresses(iface)
            logger.info(f"Found USB Wi-Fi interface: {iface} with details: {iface_details}")

            iface_truncate = iface[-4:]
            net_namespace = f"{iface_truncate}-ns"

            # Check if namespace exists, if not, create it
            try:
                if net_namespace not in netns.listnetns():
                    logger.info(f"Creating network namespace: {net_namespace} ...")
                    netns.create(net_namespace)
                else:
                    logger.info(f"Namespace {net_namespace} already exists.")
            except Exception as e:
                logger.error(f"Error during namespace handling: {e}")
                continue  # Skip to next interface if there's an error

            # Move the interface to the new network namespace
            try:
                with ipdb.interfaces[iface] as interf:
                    interf.down()  # Ensure the interface is down before moving
                    interf.net_ns_fd = net_namespace
                    logger.info(f"Moved {iface} to {net_namespace}")
            except Exception as e:
                logger.error(f"Error moving interface: {e}")

# Close IPDB
ipdb.release()


在尝试创建一个新的名称空间之前,代码使用netns.listnetns()检查它是否已经存在。这样可以防止与尝试创建一个已经存在的名称空间相关的错误。
这包括围绕命名空间操作的try-except块,以处理在创建或验证命名空间期间可能发生的任何异常。以及更多的日志记录语句,以便更好地跟踪过程,特别是关于命名空间操作的过程。

相关问题