Pipe Manual

Profile manual

Networks and the tunnel

On this page
  1. Subnet expressions
  2. [SSID Setting]
  3. The tunnel
  4. [IP Rewrite]
  5. [Snell Server]
  6. [MTProto]
  7. [Port Forwarding]
  8. Gateway Mode

What changes with the network the device is on, what Pipe's iOS VPN tunnel takes in, and on a Mac, the network it serves.

[General]
ipv6-vif = auto
tun-excluded-routes = 192.168.0.0/16
tun-included-routes = 10.7.0.1/32

[SSID Setting]
TYPE:CELLULAR cellular-fallback=off
SSID:Home dns-server=192.168.1.1, encrypted-dns-server=off
SSID:Hotel* suspend=true

[IP Rewrite]
10.7.0.1 = reflect

[Port Forwarding]
127.0.0.1:6841 db.internal.example:3306 policy=Office

Subnet expressions#

Subnet groups, SUBNET rules and [SSID Setting] lines name networks with subnet expressions.

Expression Holds
SSID:Home, SSID:Office* On Wi-Fi whose name matches, in its case. * is any run of characters and ? one character.
BSSID:aa:bb:cc:dd:ee:ff On Wi-Fi with that access point, in any case. * and ? work too.
ROUTER:192.168.1.1 On a network whose router — the default gateway — is that address.
TYPE:WIFI, TYPE:WIRED, TYPE:CELLULAR On that kind of network.
MCCMNC:001-01 On cellular, not on Wi-Fi, with that carrier's MCC and MNC. Only the digits count: 00101 is the same.
RADIO:LTE On cellular, with that radio, in any case: LTE, NRNSA, NR, WCDMA, …
CARRIER:Example Mobile, CARRIER:001-01 On cellular, with that carrier, by its name (in any case) or its MCC and MNC.
  • A prefix is read in any case: ssid: is SSID:.
  • An expression has its prefix. One without (Home, 192.168.1.1) is not one: a SUBNET rule with it is an error, and a subnet group's condition or an [SSID Setting] line with it is warned about, and left out. A Surge profile's are given theirs when it is imported.
  • An expression with a prefix and nothing after it is not one, and is warned about where it stands.
  • RADIO: and CARRIER: are what CELLULAR-RADIO and CELLULAR-CARRIER rules come to.

What a network is — its kind, its router, its Wi-Fi name and BSSID where iOS gives them, its radio and carrier on cellular — is what the app last said of it. Expressions are tried against it connection by connection, so a change of network is felt by the next connection.

On a Mac, a network reached over Ethernet may have Wi-Fi associated beside it. SSID and BSSID expressions match the primary network alone, unless subnet-exp-wifi-always-match = true says they keep matching while Wi-Fi is not the primary interface. TYPE:WIFI is about the primary network either way.

[SSID Setting]#

Each line names networks with a subnet expression, then says what changes on them: <networks> key=value, ….

[SSID Setting]
TYPE:CELLULAR suspend=true
SSID:Home dns-server=192.168.1.1, 192.168.1.2, encrypted-dns-server=off
SSID:Office* encrypted-dns-server=https://dns.corp.example/dns-query
SSID:My Phone's Hotspot cellular-fallback=off, tfo-behaviour=force-disabled
  • The expression ends where the first key= begins: a Wi-Fi name may hold spaces.
  • For each kind of setting — suspending, DNS servers, cellular and Fast Open — the first line that gives it and whose networks hold the device's network applies.
  • Settings are separated by commas. A list of servers runs on to the next key=.
Key Values What it does
suspend true, false Traffic goes directly on these networks, whatever the mode and rules.
dns-server servers, as dns-server takes them Plain servers for these networks.
encrypted-dns-server servers, as encrypted-dns-server takes them, or off Encrypted servers for these networks; off: none.
cellular-fallback default, off, wifi-assist, hybrid What these networks do with cellular. off: neither Wi-Fi Assist nor Hybrid. wifi-assist, hybrid: that one. default: as the profile says (Leaving the device).
tfo-behaviour auto, force-enabled, force-disabled force-disabled turns TCP Fast Open off on these networks; force-enabled uses it for every policy that asks for it. The system's own detection of networks that break Fast Open stays the system's.
cellular-mode true, false On a computer, these networks are metered (below).

Which DNS servers a network gets:

  • its own encrypted servers, when the line gives some;
  • or else the profile's encrypted servers, unless the line says encrypted-dns-server=off;
  • with no encrypted servers, its own plain servers, or else the profile's.

So plain servers alone do not turn the profile's encrypted ones off: SSID:Home dns-server=192.168.1.1, encrypted-dns-server=off does.

A line without a key=, or whose expression Pipe cannot read, is warned about, and left out. cellular-mode on iOS is read past without a word: it belongs to a computer. Any other key is noted, and read past. A value Pipe cannot read is warned about, and that setting is left out.

Metered Network Mode#

A phone's hotspot costs by the byte, and a computer has applications that take all they are given. On a Mac or a Linux host, a network can be said to be metered:

[SSID Setting]
SSID:PhoneHotspot cellular-mode=true
  • There, only the applications on the list you keep in the app reach the internet. Connections from anything else are refused, those whose process cannot be told included.
  • Names on the list match as PROCESS-NAME does: an executable's name, or its path when written as one, in any case.
  • The mode decides before anything else does: what it lets through goes on as the claims, the mode and the rules say. The local network, and external programs' own connections, are not held back.
  • Pipe's own requests, for rule lists and the like, are not held back.
  • The list lives in the app: it is given to the engine with POST /metered, as {"allowed": ["Safari", "/usr/bin/curl"]}. So is the switch by hand: {"manual": "on"} or "off", whatever the network, and "auto" to go by the network again. GET /metered says where it stands.

The tunnel#

On iOS, Pipe takes traffic in through a VPN tunnel. These [General] keys say what it takes in. The tunnel's own addresses are in 198.18.0.0/15: its address, its DNS server, and the fake IPs names are answered with.

ipv6-vif#

Whether the tunnel carries IPv6.

Value What it does
disabled, the default The tunnel carries IPv4 alone. Names are answered with IPv4 addresses, so only an app that connects to an IPv6 address itself goes past the tunnel.
auto It carries IPv6 while the network the phone is on has IPv6: looked at when the tunnel starts, and again whenever the network changes.
always It always carries IPv6. Noted: it can break apps on a network without IPv6.

Any other value is warned about, and disabled is used.

On a Mac, a tunnel that carries IPv6 also answers names with fake IPv6 addresses, and takes DNS at fd00:6152::2, which is what a network of IPv6 alone needs. A tun-excluded-routes range that holds fd00:6152::/64 is left out, with a warning.

tun-excluded-routes#

tun-excluded-routes = 192.168.0.0/16, 10.0.0.0/8, 239.255.255.250

Address ranges, IPv4 and IPv6, that go past the tunnel as if it were not there.

  • An address alone is a route to that address. Bits past the prefix are ignored (10.1.2.3/8 is 10.0.0.0/8), and a range written twice is one.
  • An IPv6 range while the tunnel carries no IPv6 changes nothing, and is warned about.
  • A range that would take the tunnel's own addresses past it — anything that overlaps 198.18.0.0/15 — is warned about and left out: no name would be reachable.
  • What cannot be read is warned about, and left out.

tun-included-routes#

tun-included-routes = 100.64.0.0/10, 10.7.0.1/32

Ranges the tunnel claims besides its default route: smaller routes, which win over the network's own routes for the same addresses — to reach through Pipe an address the local network would otherwise take.

  • 0.0.0.0/0 is the tunnel's default route, which it has anyway: noted.
  • A range that is in tun-excluded-routes too stays out of the tunnel, with a warning.
  • A range that holds a whole local-network range — 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 — is noted: claiming one is normally unnecessary, and can cause trouble on the device. An address inside one, such as 10.7.0.1/32, is not.
  • An IPv6 range while the tunnel carries no IPv6 changes nothing, and is warned about.

What iOS lets past the tunnel#

Key What it does
include-all-networks iOS sends everything into the tunnel, even what an app sends out of a network of its own choosing.
include-local-networks The local network goes into the tunnel too.
include-apns Apple's push notifications go into the tunnel too.
include-cellular-services The carrier's services — calls over Wi-Fi, MMS, voicemail — go into the tunnel too.
include-device-communication Talking to devices over USB and Wi-Fi — Xcode, a Mac — goes into the tunnel too.

All are false unless set. The four after the first mean something only with include-all-networks = true: without it, each is warned about and changes nothing.

icmp-forwarding#

On unless set to false. A ping sent into the tunnel is sent on by Pipe — to the real address behind a fake IP's name — and its reply brought back, so that ping works through the tunnel. With false, pings into the tunnel are dropped.

udp-priority#

With true, when packets wait to be written back into the tunnel, UDP, DNS answers and pings go before TCP, so that a game's datagram does not queue behind a download. Off unless set.

In pipe run, which sets up no tunnel, these settings change nothing, and are read past without a word.

[IP Rewrite]#

address or range = action

[General]
tun-included-routes = 10.7.0.1/32

[IP Rewrite]
10.7.0.1 = reflect
203.0.113.0/24 = drop
198.51.100.7 = reject

Each line decides what happens to the tunnel's packets for an address or a range — by where they go — before anything else sees them: the TCP and UDP stacks, the rules, the policies. The first line that matches decides.

Action What happens
reflect The packet goes back to the device with its source and destination swapped, so that an address in the tunnel stands for the device itself, as developer services on the device need.
reject TCP is answered with a reset, anything else with ICMP's "administratively prohibited": the sender fails at once.
drop Nothing comes back.

Only packets that enter the tunnel can be rewritten: to rewrite an address the network would otherwise take, claim it with tun-included-routes. A line that is not address = action, whose address is not one, or whose action is none of these, is warned about and left out.

[Snell Server]#

On a Mac or a Linux host, Pipe serves Snell itself, for your other devices:

[Snell Server]
interface = 0.0.0.0
port = 6160
psk = a-key-of-your-own
version = 4
obfs = off
Key Values Default What it does
port a port required Where it listens.
psk text required The key its clients share. Version 6 takes 12 to 255 bytes.
interface an address 0.0.0.0 The address it listens on.
version 1 to 6 4 The Snell version it speaks. 5 also takes version 4 clients.
mode default, unshaped, unsafe-raw default Version 6's kind of records, as its clients have it. unsafe-raw seals nothing, and needs a userkey.
obfs off, http, tls off simple-obfs around each connection, versions 1 to 5. obfs-host is noted, and read past: the server takes off whatever host a client shows.
userkey a list none The user keys requests may carry; none, and any user of the psk is taken.
  • Each client connection and UDP tunnel goes through the profile's rules and policies, as any connection does, and shows in the connection table under the inbound's name.
  • It serves the local network alone unless proxy-restricted-to-lan = false says otherwise: it is on your network that you share it.
  • A section that cannot be read is warned about, and no server runs.
  • On iOS the section is kept in the file and read past without a word, as a computer's. A module cannot run a server.

[MTProto]#

On a Mac or a Linux host, Pipe serves Telegram's MTProxy, for the Telegram apps on your other devices. A profile has one:

[MTProto]
interface = 0.0.0.0
port = 8443
secret = dd00112233445566778899aabbccddeeff
Key Values Default What it does
port a port required Where it listens.
secret 32 hex digits, after an optional dd required What a client has to know. With dd, clients must use padded framing, which says less on the wire. An ee secret is Fake TLS, which Pipe does not speak: the server is not run, and that is said.
interface an address 0.0.0.0 The address it listens on.
ipv6 true, false false Data centers are reached over IPv6.
dc-config-url a URL none Where the data centers' addresses are kept current from, as below.
  • A client's connection goes to the data center it asks for, through the profile's rules and policies: PROTOCOL,MTPROTO,Proxy chooses the policy, and it shows in the connection table under the inbound's name.
  • A client with the wrong secret hears nothing, and is not closed on sooner than one that said too little. An opening seen before is treated as a wrong one: someone recorded it.
  • It serves the local network alone unless proxy-restricted-to-lan = false says otherwise.

Pipe knows Telegram's published data center addresses. A dc-config-url replaces them, read when Pipe starts and daily after: a file of at most 64 KiB and 256 addresses, of proxy_for <dc> <address>:<port>; lines and default <dc>;, as Telegram's getProxyConfig is written. Pipe connects to data centers directly, so a line on port 8888, a middle proxy's, is left out: Telegram's own file comes to nothing that way, and a file that comes to nothing leaves the addresses as they were.

[Port Forwarding]#

listen-address:port target-host:port [policy=Policy]

[Port Forwarding]
127.0.0.1:6841 db.internal.example:3306 policy=Office
0.0.0.0:8022 10.0.0.5:22

Each line listens on the address and port it gives, and sends every TCP connection made to it on to the target — through the policy it names, or, without one, where the rules send it.

  • The listen address is an address and a port: 127.0.0.1:6841 serves the device's own apps; 0.0.0.0:8022 other devices too.
  • A port listening beyond the device itself serves only devices on the local network, while proxy-restricted-to-lan is on (the default), as the shared proxy does.
  • The target is host:port: a name or an address.
  • A policy the profile does not have is an error. A REJECT one is warned about, and the port is not forwarded.
  • IN-PORT rules see the listen port.
  • A line Pipe cannot read is warned about, and left out. A parameter other than policy is noted, and read past.

Gateway Mode#

On a Mac, Pipe can be the way out of the local network for devices that run no proxy themselves: consoles, TVs, a printer's firmware. They use the Mac as their gateway and their DNS, and what they send goes through the rules like the Mac's own. The Mac needs Enhanced Mode on, and an address of its own on the network that does not change.

[General]
gateway-restricted-to-lan = true

[DHCP]
default-lease-time = 3600
min-lease-time = 300
max-lease-time = 86400
one-lease-per-client = true
ping-check = true

[Rule]
DEVICE-NAME,Apple-TV,Proxy
MAC-ADDRESS,aa:bb:cc:dd:ee:ff,DIRECT
SRC-IP,192.168.1.60,Proxy
FINAL,Proxy

A device is given the Mac as its gateway by hand, in its own network settings, or by Pipe's DHCP server, which also gives it the tunnel's DNS address. On a phone there is no gateway: [DHCP] is read past without a word, and DEVICE-NAME and MAC-ADDRESS rules are left out with a warning.

  • The gateway carries IPv4. A network that also has IPv6 routers keeps giving devices a way past it.
  • With gateway-restricted-to-lan (the default), a flow from outside the local network is dropped as it begins.
  • Every device's flows are the Mac's to carry: a connection's record says which device it came from, and the device list what each carried.

[DHCP]#

Pipe's DHCP server answers on the one interface the app names. Before it answers anything it listens for another DHCP server there, a few seconds, and stands down if it hears one, usually the router's: two servers on a network hand out one address twice. It looks again every five minutes, and also stands down if a device asks for an address from another server. Turn the router's DHCP off to use Pipe's.

Key Values Default What it does
default-lease-time seconds 3600 How long an address is given for, to a device that does not ask.
min-lease-time, max-lease-time seconds 300, 86400 The least and the most a device that asks is given. At most 90 days.
one-lease-per-client true, false true A device is its hardware address. false: a device that sends a client identifier is that identifier, so that two systems on one machine have an address each.
ping-check true, false true An address new to a device is checked first, and passed over for ten minutes if something answers.
  • A value that cannot be read is warned about, and its default is used. So is a time past 90 days. Bounds that disagree are warned about, and made to agree; a default outside them is brought inside.
  • A device keeps its address for as long as nobody else needs it. Leases are kept across restarts.
  • An address the Mac sees in use that no lease explains is a device's own, set by hand, and is left alone.
  • A device can have an address reserved: it always gets that one, and no other device gets it. It may lie outside the pool, on the subnet.
  • A module cannot change [DHCP].

Devices#

Pipe lists the devices it hears of: from DHCP, from the Mac's neighbour table, and from their connections. Each has a name you give it, or else the one it gave DHCP. Names, reservations and what each carried are kept across restarts, for up to 1,024 devices; those you named stay.

DEVICE-NAME matches a device's name, MAC-ADDRESS its hardware address, and SRC-IP its address. A connection from a device Pipe has no name for has no DEVICE-NAME. A connection from the Mac itself is no device's: only SRC-IP sees it.

The UDP fast path#

Some software talks to hundreds of peers over UDP, a few packets each. A device that opens 10 UDP flows within a second, or 30 within ten seconds, has its new flows sent straight out for the next minute, past the rules: Pipe stops deciding each one. What is already under way stays as it is.

  • Destination ports below 1024 stay with the rules, and so does every flow to a name. Only an address given by the device itself goes this way.
  • In Global mode and with an exit node, nothing does.
  • A device can be pinned to either way: always the fast path, or never.
  • These flows are in no connection list, and go out directly whatever the rules say. Pin a device to never when that matters for it.