Skip to content

Commit

Permalink
Add nat-lab test for starting telio with an existing tunnel
Browse files Browse the repository at this point in the history
Also fix some bugs found on the way.
  • Loading branch information
ThrasherLT committed Dec 18, 2024
1 parent 237d70f commit cb22eec
Show file tree
Hide file tree
Showing 11 changed files with 106 additions and 4 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ windows = { version = "0.56", features = [
"Win32_NetworkManagement_IpHelper",
] }

neptun = { git = "https://github.com/NordSecurity/neptun.git", tag = "v1.0.0", features = ["device"] }
neptun = { git = "https://github.com/NordSecurity/neptun.git", branch = "jj_uapi_buf_fix", features = ["device"] }
x25519-dalek = { version = "2.0.1", features = ["reusable_secrets", "static_secrets"] }


Expand Down
2 changes: 0 additions & 2 deletions crates/telio-wg/src/adapter/neptun.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,6 @@ impl NepTUN {
protect: socket_pool,
firewall_process_inbound_callback,
firewall_process_outbound_callback,
#[cfg(target_os = "linux")]
uapi_fd: -1,
};

let device = match tun {
Expand Down
13 changes: 13 additions & 0 deletions nat-lab/tests/telio.py
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,19 @@ async def simple_start(self):
if isinstance(self.get_router(), LinuxRouter):
await self.get_proxy().set_fwmark(int(LINUX_FWMARK_VALUE))

async def create_tun(self, tun_name: str) -> int:
return await self.get_proxy().create_tun(tun_name)

async def start_with_tun(self, tun: int, tun_name):
await self.get_proxy().start_with_tun(
private_key=self._node.private_key,
adapter=self._adapter_type,
tun=tun,
)
if isinstance(self.get_router(), LinuxRouter):
self.get_router().set_interface_name(tun_name)
await self.get_proxy().set_fwmark(int(LINUX_FWMARK_VALUE))

async def wait_for_state_peer(
self,
public_key,
Expand Down
41 changes: 41 additions & 0 deletions nat-lab/tests/test_start_with_tun.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from typing import List
from contextlib import AsyncExitStack
from helpers import SetupParameters, ping_between_all_nodes, setup_mesh_nodes
from utils.bindings import (
default_features,
TelioAdapterType,
)
from utils.connection_util import ConnectionTag


def _generate_setup_parameters(
conn_tags: List[ConnectionTag],
) -> List[SetupParameters]:
return [
SetupParameters(
connection_tag=conn_tag,
adapter_type_override=TelioAdapterType.BORING_TUN,
features=default_features(),
fingerprint=f"{conn_tag}",
)
for conn_tag in conn_tags
]


async def test_start_with_tun() -> None:
setup_params = _generate_setup_parameters([
ConnectionTag.DOCKER_CONE_CLIENT_1,
ConnectionTag.DOCKER_CONE_CLIENT_2,
])

async with AsyncExitStack() as exit_stack:
env = await setup_mesh_nodes(exit_stack, setup_params)
alpha_client, _ = env.clients
alpha, _ = env.nodes

await alpha_client.stop_device()
tun = await alpha_client.create_tun("tun11")
await alpha_client.start_with_tun(tun, "tun11")
await alpha_client.set_meshnet_config(env.api.get_meshnet_config(alpha.id))
await ping_between_all_nodes(env)
await alpha_client.stop_device()
10 changes: 10 additions & 0 deletions nat-lab/tests/uniffi/libtelio_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,16 @@ def start_named(self, private_key, adapter, name: str):
lambda r: r.start_named(private_key, adapter.value, name)
)

@move_to_async_thread
def create_tun(self, tun_name: str) -> int:
return self._handle_remote_error(lambda r: r.create_tun(tun_name))

@move_to_async_thread
def start_with_tun(self, private_key, adapter, tun: int):
self._handle_remote_error(
lambda r: r.start_with_tun(private_key, adapter.value, tun)
)

@move_to_async_thread
def set_fwmark(self, fwmark: int):
self._handle_remote_error(lambda r: r.set_fwmark(fwmark))
Expand Down
23 changes: 23 additions & 0 deletions nat-lab/tests/uniffi/libtelio_remote.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import datetime
import fcntl
import os
import struct
import Pyro5.api # type: ignore
import Pyro5.server # type: ignore
import shutil
Expand Down Expand Up @@ -109,6 +111,27 @@ def start_named(self, private_key, adapter, name: str):
private_key, libtelio.TelioAdapterType(adapter), name
)

@serialize_error
def create_tun(self, tun_name: str) -> int:
# Constants for TUN/TAP interface creation (from Linux's if_tun.h)
TUNSETIFF = 0x400454CA
IFF_TUN = 0x0001
IFF_MULTI_QUEUE = 0x0100
IFF_NO_PI = 0x1000
tun_name_bytes = tun_name.encode("ascii")
tun_fd = os.open("/dev/net/tun", os.O_RDWR)
# '16sH' means we need to pass 16-byte string (interface name) and 2-byte short (flags)
ifr = struct.pack("16sH", tun_name_bytes, IFF_TUN | IFF_MULTI_QUEUE | IFF_NO_PI)
fcntl.ioctl(tun_fd, TUNSETIFF, ifr)

return tun_fd

@serialize_error
def start_with_tun(self, private_key, adapter, tun: int):
self._libtelio.start_with_tun(
private_key, libtelio.TelioAdapterType(adapter), tun
)

@serialize_error
def set_fwmark(self, fwmark: int):
self._libtelio.set_fwmark(fwmark)
Expand Down
3 changes: 3 additions & 0 deletions nat-lab/tests/utils/router/linux_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ async def setup_interface(self, addresses: List[str]) -> None:
["ip", "link", "set", "up", "dev", self._interface_name]
).execute()

def set_interface_name(self, new_interface_name: str) -> None:
self._interface_name = new_interface_name

async def deconfigure_interface(self, addresses: List[str]) -> None:
for address in addresses:
await self._connection.create_process(
Expand Down
5 changes: 5 additions & 0 deletions nat-lab/tests/utils/router/mac_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,8 @@ async def block_udp_port(
@asynccontextmanager
async def reset_upnpd(self) -> AsyncIterator:
yield

def set_interface_name(
self, new_interface_name: str # pylint: disable=unused-argument
) -> None:
pass
4 changes: 4 additions & 0 deletions nat-lab/tests/utils/router/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ def check_ip_address(self, address: str) -> Optional[IPProto]:
def get_interface_name(self) -> str:
pass

@abstractmethod
def set_interface_name(self, new_interface_name: str) -> None:
pass

@abstractmethod
async def setup_interface(self, addresses: List[str]) -> None:
pass
Expand Down
5 changes: 5 additions & 0 deletions nat-lab/tests/utils/router/windows_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,3 +324,8 @@ async def block_udp_port(
@asynccontextmanager
async def reset_upnpd(self) -> AsyncIterator:
yield

def set_interface_name(
self, new_interface_name: str # pylint: disable=unused-argument
) -> None:
pass

0 comments on commit cb22eec

Please sign in to comment.