psiphon 2.0.2__tar.gz → 2.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {psiphon-2.0.2 → psiphon-2.0.3}/PKG-INFO +17 -1
- {psiphon-2.0.2 → psiphon-2.0.3}/README.md +16 -0
- {psiphon-2.0.2 → psiphon-2.0.3}/pyproject.toml +1 -1
- {psiphon-2.0.2 → psiphon-2.0.3}/src/psiphon/routing.py +47 -0
- {psiphon-2.0.2 → psiphon-2.0.3}/LICENSE +0 -0
- {psiphon-2.0.2 → psiphon-2.0.3}/src/psiphon/__init__.py +0 -0
- {psiphon-2.0.2 → psiphon-2.0.3}/src/psiphon/assets/LICENSE.engine +0 -0
- {psiphon-2.0.2 → psiphon-2.0.3}/src/psiphon/assets/psiphon.config +0 -0
- {psiphon-2.0.2 → psiphon-2.0.3}/src/psiphon/config.py +0 -0
- {psiphon-2.0.2 → psiphon-2.0.3}/src/psiphon/engine.py +0 -0
- {psiphon-2.0.2 → psiphon-2.0.3}/src/psiphon/main.py +0 -0
- {psiphon-2.0.2 → psiphon-2.0.3}/src/psiphon/network.py +0 -0
- {psiphon-2.0.2 → psiphon-2.0.3}/src/psiphon/supervisor.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: psiphon
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.3
|
|
4
4
|
Summary: Foreground native Psiphon packet tunnel and explicit local proxy for Linux
|
|
5
5
|
Author: KpihX
|
|
6
6
|
Author-email: KpihX <kapoivha@gmail.com>
|
|
@@ -132,6 +132,22 @@ Tailscale/campus DNS present. Sixteen produced verified packet-tunnel downloads;
|
|
|
132
132
|
all sessions restored the original routes and per-link DNS domains. See
|
|
133
133
|
`BENCHMARKS.md` for failures and qualifications.
|
|
134
134
|
|
|
135
|
+
### 2.0.3: local container/VM bridge exception
|
|
136
|
+
|
|
137
|
+
The broad nonlocal IPv4 statement above now has one explicit exception: existing
|
|
138
|
+
directly connected IPv4 prefixes on Linux bridges stay on those bridges. Their
|
|
139
|
+
routes are copied into the temporary VPN table, not changed in the main table,
|
|
140
|
+
and removed in reverse rollback. This keeps Docker/VM local APIs reachable while
|
|
141
|
+
Internet traffic still selects the TUN. It is not a blanket RFC1918, WiFi LAN or
|
|
142
|
+
physical-uplink bypass. New bridges created after connection are not automatically
|
|
143
|
+
watched; reconnect when adding network topology during a session.
|
|
144
|
+
|
|
145
|
+
The failure was reproduced with Docker traffic selecting psiphon0. After the fix,
|
|
146
|
+
a live Germany session kept the container path local and returned the xsearch
|
|
147
|
+
engine inventory and real search results over both Unix IPC and TCP. iproute2
|
|
148
|
+
omits the `scope` field in some filtered JSON results; the regression fixture
|
|
149
|
+
uses this observed shape, not an assumed schema.
|
|
150
|
+
|
|
135
151
|
Each successful mutation has an inverse. The supervisor owns the engine and
|
|
136
152
|
observes a private pipe: normal exit, startup failure, SIGTERM, Ctrl-C or controller
|
|
137
153
|
SIGKILL closes it, stops/reaps the engine, and rolls back in reverse order. Cleanup
|
|
@@ -115,6 +115,22 @@ Tailscale/campus DNS present. Sixteen produced verified packet-tunnel downloads;
|
|
|
115
115
|
all sessions restored the original routes and per-link DNS domains. See
|
|
116
116
|
`BENCHMARKS.md` for failures and qualifications.
|
|
117
117
|
|
|
118
|
+
### 2.0.3: local container/VM bridge exception
|
|
119
|
+
|
|
120
|
+
The broad nonlocal IPv4 statement above now has one explicit exception: existing
|
|
121
|
+
directly connected IPv4 prefixes on Linux bridges stay on those bridges. Their
|
|
122
|
+
routes are copied into the temporary VPN table, not changed in the main table,
|
|
123
|
+
and removed in reverse rollback. This keeps Docker/VM local APIs reachable while
|
|
124
|
+
Internet traffic still selects the TUN. It is not a blanket RFC1918, WiFi LAN or
|
|
125
|
+
physical-uplink bypass. New bridges created after connection are not automatically
|
|
126
|
+
watched; reconnect when adding network topology during a session.
|
|
127
|
+
|
|
128
|
+
The failure was reproduced with Docker traffic selecting psiphon0. After the fix,
|
|
129
|
+
a live Germany session kept the container path local and returned the xsearch
|
|
130
|
+
engine inventory and real search results over both Unix IPC and TCP. iproute2
|
|
131
|
+
omits the `scope` field in some filtered JSON results; the regression fixture
|
|
132
|
+
uses this observed shape, not an assumed schema.
|
|
133
|
+
|
|
118
134
|
Each successful mutation has an inverse. The supervisor owns the engine and
|
|
119
135
|
observes a private pipe: normal exit, startup failure, SIGTERM, Ctrl-C or controller
|
|
120
136
|
SIGKILL closes it, stops/reaps the engine, and rolls back in reverse order. Cleanup
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""Conservative native TUN routing, with only session-scoped owned resources."""
|
|
2
2
|
|
|
3
|
+
import ipaddress
|
|
3
4
|
import json
|
|
4
5
|
import os
|
|
5
6
|
import re
|
|
@@ -87,6 +88,37 @@ def check_user_binding(interface: str) -> None:
|
|
|
87
88
|
) from exc
|
|
88
89
|
|
|
89
90
|
|
|
91
|
+
def connected_bridge_routes() -> list[dict]:
|
|
92
|
+
"""Keep directly-connected container/VM bridges local, not RFC1918 at large.
|
|
93
|
+
|
|
94
|
+
Only existing unicast scope-link IPv4 routes on actual Linux bridges qualify.
|
|
95
|
+
Never copy a default route, gateway, physical uplink or arbitrary policy table.
|
|
96
|
+
"""
|
|
97
|
+
links = json.loads(run(["ip", "-j", "-d", "link", "show"]))
|
|
98
|
+
bridges = {
|
|
99
|
+
link["ifname"]
|
|
100
|
+
for link in links
|
|
101
|
+
if link.get("linkinfo", {}).get("info_kind") == "bridge"
|
|
102
|
+
}
|
|
103
|
+
routes = json.loads(
|
|
104
|
+
run(["ip", "-j", "-4", "route", "show", "table", "main", "scope", "link"])
|
|
105
|
+
)
|
|
106
|
+
selected = []
|
|
107
|
+
for route in routes:
|
|
108
|
+
if (
|
|
109
|
+
route.get("dev") not in bridges
|
|
110
|
+
or route.get("gateway")
|
|
111
|
+
or route.get("type", "unicast") != "unicast"
|
|
112
|
+
# iproute2 omits "scope" in JSON when the scope=link filter is used.
|
|
113
|
+
or route.get("scope", "link") != "link"
|
|
114
|
+
):
|
|
115
|
+
continue
|
|
116
|
+
network = ipaddress.ip_network(route.get("dst", "0.0.0.0/0"), strict=False)
|
|
117
|
+
if network.version == 4 and network.prefixlen:
|
|
118
|
+
selected.append({"dst": str(network), "dev": route["dev"]})
|
|
119
|
+
return selected
|
|
120
|
+
|
|
121
|
+
|
|
90
122
|
def configure(owner, uplink: str, uid: int | None = None) -> None:
|
|
91
123
|
tun = config.TUN_NAME
|
|
92
124
|
owner.apply(
|
|
@@ -124,6 +156,21 @@ def configure(owner, uplink: str, uid: int | None = None) -> None:
|
|
|
124
156
|
["ip", family, "route", "add", *route, "table", config.ROUTE_TABLE],
|
|
125
157
|
["ip", family, "route", "del", *route, "table", config.ROUTE_TABLE],
|
|
126
158
|
)
|
|
159
|
+
if family == "-4":
|
|
160
|
+
for local in connected_bridge_routes():
|
|
161
|
+
direct = [
|
|
162
|
+
local["dst"],
|
|
163
|
+
"dev",
|
|
164
|
+
local["dev"],
|
|
165
|
+
"scope",
|
|
166
|
+
"link",
|
|
167
|
+
"table",
|
|
168
|
+
config.ROUTE_TABLE,
|
|
169
|
+
]
|
|
170
|
+
owner.apply(
|
|
171
|
+
["ip", "-4", "route", "add", *direct],
|
|
172
|
+
["ip", "-4", "route", "del", *direct],
|
|
173
|
+
)
|
|
127
174
|
# Explicitly uplink-bound IPv4 sockets bypass (required by ConsoleClient).
|
|
128
175
|
# IPv6 is blocked for all nonlocal traffic for this session.
|
|
129
176
|
if family == "-4":
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|