Run the tailnet SOCKS proxy in Swift so the iPhone app reconnects

This commit is contained in:
Ian Gulliver
2026-10-22 08:11:32 -07:00
parent e28071f380
commit 519199eba4
4 changed files with 202 additions and 18 deletions
+3 -16
View File
@@ -27,9 +27,7 @@ func slug(_ text: String) -> String {
final class TailnetNode: Sendable {
let sd: tailscale
let hostname = "byre-app-\(slug(deviceName))"
private let proxyHost: String
private let proxyPort: UInt16
private let proxyCredential: String
private let socks = TailnetProxy()
init() {
let dir = URL.applicationSupportDirectory.appending(path: "run.fc.byre.mac/tsnet", directoryHint: .isDirectory)
@@ -43,17 +41,6 @@ final class TailnetNode: Sendable {
Self.check(sd, "set dir", unsafe tailscale_set_dir(sd, dir.path))
Self.check(sd, "set ephemeral", tailscale_set_ephemeral(sd, 0))
Self.check(sd, "start", tailscale_start(sd))
var addr = [CChar](repeating: 0, count: 64)
var proxyCred = [CChar](repeating: 0, count: 33)
var apiCred = [CChar](repeating: 0, count: 33)
Self.check(sd, "loopback", unsafe tailscale_loopback(sd, &addr, addr.count, &proxyCred, &apiCred))
let address = String(decoding: addr.prefix { $0 != 0 }.map { UInt8(bitPattern: $0) }, as: UTF8.self)
guard let colon = address.lastIndex(of: ":"), let port = UInt16(address[address.index(after: colon)...]) else {
fatalError("tsnet loopback address \(address)")
}
proxyHost = String(address[..<colon])
proxyPort = port
proxyCredential = String(decoding: proxyCred.prefix { $0 != 0 }.map { UInt8(bitPattern: $0) }, as: UTF8.self)
}
static func check(_ sd: tailscale, _ what: String, _ result: Int32) {
@@ -69,8 +56,8 @@ final class TailnetNode: Sendable {
}
func proxy() -> ProxyConfiguration {
let proxy = ProxyConfiguration(socksv5Proxy: .hostPort(host: NWEndpoint.Host(proxyHost), port: NWEndpoint.Port(rawValue: proxyPort)!))
proxy.applyCredential(username: "tsnet", password: proxyCredential)
let proxy = ProxyConfiguration(socksv5Proxy: .hostPort(host: .ipv4(.loopback), port: NWEndpoint.Port(rawValue: socks.port)!))
proxy.applyCredential(username: "byre", password: socks.credential)
return proxy
}