tunnel

package
v1.0.122 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 24, 2024 License: MIT Imports: 42 Imported by: 5

Documentation

Overview

Package tunnel implements creating a TUN interface for iOS 17 devices. These tunnels are used to connect to services running on the device. On older iOS versions this was done over the 'usbmuxd'-socket. Services that are available via usbmuxd can also be used over the tunnel (they are listed in remote service discovery).

Starting a tunnel is a two-step process:

- Pair Device/Verify Device Pairing

- Setting up a TUN interface

Device Pairing

The step of device pairing means either that a new pairing is set up, or credentials from an already existing pairing are verified. For device pairing we connect to the RemoteXPC service 'com.apple.internal.dt.coredevice.untrusted.tunnelservice' directly on the ethernet interface exposed by the device. Process: - host -> device : 'setupManualPairing' request

- device -> host : device public key and salt to initialize SRP

- host -> device : host public key and SRP client proof

- device -> host : SRP host proof

- host -> device : host info (signed with the key from the host pair record) encrypted with the session key obtained through SRP

- device -> host : device info encrypted with the same key as above

Verifying a device pairing works by signing the host identifier (which is part of the pair record on the host) with a key derived through ECDH. The public keys used there are the key of the pair record on the host and the device provides a public key when the host asks to verify the pairing.

Tunnel Interface

For the TUN interface we continue to use the same connection that we opened for the device pairing. The host asks the device to create a listener, and provides a public key, as well as the requested tunnel type. There are two types of tunnels that can be created, QUIC and TCP. In this package only QUIC is supported. The device will respond with a public key and a port number on which the tunnel endpoint listens on the device. The host opens a QUIC connection using a self-signed certificate with the public key that was sent to the device earlier. The first messages on this QUIC connection exchange the parameters for this tunnel. The host sends a 'clientHandshakeRequest' containing the MTU used for the TUN interface, and the device responds with the information about what IP addresses the host and the device have to use for this tunnel, as well as the port on which remote service discovery (RSD) is reachable on the device

After that all services listed in RSD are available via this TUN interface

SPDX-License-Identifier: MIT
*
* Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.

taken from package wireguard-go/tun/tun_windows.go to minimize useless dependencies and transparently drop ipv4 packets

Index

Constants

View Source
const (
	EventUp = 1 << iota
	EventDown
	EventMTUUpdate
)
View Source
const DefaultHttpApiPort = 28100

DefaultHttpApiPort is the port on which we start the HTTP-Server for exposing started tunnels

Variables

View Source
var (
	WintunTunnelType          = "WireGuard"
	WintunStaticRequestedGUID *windows.GUID
)

Functions

func ServeTunnelInfo

func ServeTunnelInfo(tm *TunnelManager, port int) error

ServeTunnelInfo starts a simple http serve that exposes the tunnel information about the running tunnel. The API has two endpoints: 1. GET localhost:{PORT}/tunnel/{UDID} to get the tunnel info for a specific device 2. DELETE localhost:{PORT}/tunnel/{UDID} to stop a device tunnel 3. GET localhost:{PORT}/tunnels to get a list of all tunnels

Types

type Device

type Device interface {
	// File returns the file descriptor of the device.
	File() *os.File

	// Read one or more packets from the Device (without any additional headers).
	// On a successful read it returns the number of packets read, and sets
	// packet lengths within the sizes slice. len(sizes) must be >= len(bufs).
	// A nonzero offset can be used to instruct the Device on where to begin
	// reading into each element of the bufs slice.
	Read(bufs [][]byte, sizes []int, offset int) (n int, err error)

	// Write one or more packets to the device (without any additional headers).
	// On a successful write it returns the number of packets written. A nonzero
	// offset can be used to instruct the Device on where to begin writing from
	// each packet contained within the bufs slice.
	Write(bufs [][]byte, offset int) (int, error)

	// MTU returns the MTU of the Device.
	MTU() (int, error)

	// Name returns the current name of the Device.
	Name() (string, error)

	// Events returns a channel of type Event, which is fed Device events.
	Events() <-chan Event

	// Close stops the Device and closes the Event channel.
	Close() error

	// BatchSize returns the preferred/max number of packets that can be read or
	// written in a single read/write call. BatchSize must not change over the
	// lifetime of a Device.
	BatchSize() int
}

func CreateTUN

func CreateTUN(ifname string, mtu int) (Device, error)

CreateTUN creates a Wintun interface with the given name. Should a Wintun interface with the same name exist, it is reused.

func CreateTUNWithRequestedGUID

func CreateTUNWithRequestedGUID(ifname string, requestedGUID *windows.GUID, mtu int) (Device, error)

CreateTUNWithRequestedGUID creates a Wintun interface with the given name and a requested GUID. Should a Wintun interface with the same name exist, it is reused.

type Event

type Event int

type NativeTun

type NativeTun struct {
	// contains filtered or unexported fields
}

func (*NativeTun) BatchSize

func (tun *NativeTun) BatchSize() int

func (*NativeTun) Close

func (tun *NativeTun) Close() error

func (*NativeTun) Events

func (tun *NativeTun) Events() <-chan Event

func (*NativeTun) File

func (tun *NativeTun) File() *os.File

func (*NativeTun) ForceMTU

func (tun *NativeTun) ForceMTU(mtu int)

TODO: This is a temporary hack. We really need to be monitoring the interface in real time and adapting to MTU changes.

func (*NativeTun) LUID

func (tun *NativeTun) LUID() uint64

LUID returns Windows interface instance ID.

func (*NativeTun) MTU

func (tun *NativeTun) MTU() (int, error)

func (*NativeTun) Name

func (tun *NativeTun) Name() (string, error)

func (*NativeTun) Read

func (tun *NativeTun) Read(bufs [][]byte, sizes []int, offset int) (int, error)

func (*NativeTun) RunningVersion

func (tun *NativeTun) RunningVersion() (version uint32, err error)

RunningVersion returns the running version of the Wintun driver.

func (*NativeTun) Write

func (tun *NativeTun) Write(bufs [][]byte, offset int) (int, error)

type PairRecordManager

type PairRecordManager struct {
	// contains filtered or unexported fields
}

PairRecordManager implements the same logic as macOS related to remote pair records. Those pair records are used whenever a tunnel gets created.

func NewPairRecordManager

func NewPairRecordManager(p string) (PairRecordManager, error)

NewPairRecordManager creates a PairRecordManager that reads/stores the pair records information at the given path To use the same pair records as macOS does, this path should be /var/db/lockdown/RemotePairing/user_501 (user_501 is the default for the root user)

func (PairRecordManager) StoreDeviceInfo

func (p PairRecordManager) StoreDeviceInfo(d device) error

StoreDeviceInfo stores the provided Device info as a plist encoded file in the `peers/` directory

type Tunnel

type Tunnel struct {
	// Address is the IPv6 address of the device over the tunnel
	Address string `json:"address"`
	// RsdPort is the port on which remote service discover is reachable
	RsdPort int `json:"rsdPort"`
	// Udid is the id of the device for this tunnel
	Udid string `json:"udid"`
	// contains filtered or unexported fields
}

Tunnel describes the parameters of an established tunnel to the device

func ConnectTunnelLockdown

func ConnectTunnelLockdown(device ios.DeviceEntry) (Tunnel, error)

func ListRunningTunnels

func ListRunningTunnels(tunnelInfoPort int) ([]Tunnel, error)

func ManualPairAndConnectToTunnel

func ManualPairAndConnectToTunnel(ctx context.Context, device ios.DeviceEntry, p PairRecordManager) (Tunnel, error)

ManualPairAndConnectToTunnel tries to verify an existing pairing, and if this fails it triggers a new manual pairing process. After a successful pairing a tunnel for this device gets started and the tunnel information is returned

func TunnelInfoForDevice

func TunnelInfoForDevice(udid string, tunnelInfoPort int) (Tunnel, error)

func (Tunnel) Close

func (t Tunnel) Close() error

Close closes the connection to the device and removes the virtual network interface from the host

type TunnelManager

type TunnelManager struct {
	// contains filtered or unexported fields
}

TunnelManager starts tunnels for devices when needed (if no tunnel is running yet) and stores the information how those tunnels are reachable (address and remote service discovery port)

func NewTunnelManager

func NewTunnelManager(pm PairRecordManager) *TunnelManager

NewTunnelManager creates a new TunnelManager instance for setting up device tunnels for all connected devices

func (*TunnelManager) FindTunnel

func (m *TunnelManager) FindTunnel(udid string) (Tunnel, error)

func (*TunnelManager) ListTunnels

func (m *TunnelManager) ListTunnels() ([]Tunnel, error)

ListTunnels provides all currently running device tunnels

func (*TunnelManager) UpdateTunnels

func (m *TunnelManager) UpdateTunnels(ctx context.Context) error

UpdateTunnels checks for connected devices and starts a new tunnel if needed On device disconnects the tunnel resources get cleaned up

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL