Skip to content

Commit b544fb9

Browse files
committed
UAPI for macOS
Signed-off-by: Jan Noha <[email protected]>
1 parent 2fec12a commit b544fb9

File tree

6 files changed

+111
-13
lines changed

6 files changed

+111
-13
lines changed

Sources/Shared/Keychain.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,22 @@ class Keychain {
1818
return String(data: data, encoding: String.Encoding.utf8)
1919
}
2020

21+
static func getReferenceName(called ref: Data) -> String? {
22+
var result: CFTypeRef?
23+
let ret = SecItemCopyMatching([kSecValuePersistentRef: ref,
24+
kSecReturnAttributes: true] as CFDictionary,
25+
&result)
26+
if ret != errSecSuccess || result == nil {
27+
wg_log(.error, message: "Unable to get config attributes from keychain: \(ret)")
28+
return nil
29+
}
30+
guard let attrs = result as? [CFString: AnyObject] else { return nil }
31+
32+
guard let secAttrAccount = attrs[kSecAttrAccount] as? String else { return nil }
33+
let name = secAttrAccount.split(separator: ":", maxSplits: 1)[0]
34+
return String(name)
35+
}
36+
2137
static func makeReference(containing value: String, called name: String, previouslyReferencedBy oldRef: Data? = nil) -> Data? {
2238
var ret: OSStatus
2339
guard var bundleIdentifier = Bundle.main.bundleIdentifier else {

Sources/Shared/Model/NETunnelProviderProtocol+Extension.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,11 @@ extension NETunnelProviderProtocol {
3939
func asTunnelConfiguration(called name: String? = nil) -> TunnelConfiguration? {
4040
if let passwordReference = passwordReference,
4141
let config = Keychain.openReference(called: passwordReference) {
42-
return try? TunnelConfiguration(fromWgQuickConfig: config, called: name)
42+
var tunnelName = name
43+
if tunnelName == nil {
44+
tunnelName = Keychain.getReferenceName(called: passwordReference)
45+
}
46+
return try? TunnelConfiguration(fromWgQuickConfig: config, called: tunnelName)
4347
}
4448
if let oldConfig = providerConfiguration?["WgQuickConfig"] as? String {
4549
return try? TunnelConfiguration(fromWgQuickConfig: oldConfig, called: name)

Sources/WireGuardKit/WireGuardAdapter.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ public class WireGuardAdapter {
5656
/// Adapter state.
5757
private var state: State = .stopped
5858

59+
/// File that will contain the real interface name (called <name-of-tunnel>.name)
60+
private var wgTunNameFile: URL? = nil
61+
5962
/// Tunnel device file descriptor.
6063
private var tunnelFileDescriptor: Int32? {
6164
var ctlInfo = ctl_info()
@@ -146,6 +149,9 @@ public class WireGuardAdapter {
146149

147150
// Shutdown the tunnel
148151
if case .started(let handle, _) = self.state {
152+
if let wgTunNameFile = self.wgTunNameFile {
153+
_ = FileManager.deleteFile(at: wgTunNameFile)
154+
}
149155
wgTurnOff(handle)
150156
}
151157
}
@@ -187,6 +193,18 @@ public class WireGuardAdapter {
187193
}
188194
networkMonitor.start(queue: self.workQueue)
189195

196+
if let tunnelName = tunnelConfiguration.name, let ifaceName = self.interfaceName {
197+
let wgTunNameFile = NSHomeDirectory() + "/" + tunnelName + ".name"
198+
self.wgTunNameFile = URL(fileURLWithPath: wgTunNameFile, isDirectory: false)
199+
200+
let ifaceNameData = "\(ifaceName)\n".data(using: .utf8)
201+
if !FileManager.default.createFile(atPath: wgTunNameFile,
202+
contents: ifaceNameData,
203+
attributes: [.posixPermissions: 0o400]) {
204+
self.logHandler(.error, "Failed to write wg tun name file")
205+
}
206+
}
207+
190208
do {
191209
let settingsGenerator = try self.makeSettingsGenerator(with: tunnelConfiguration)
192210
try self.setNetworkSettings(settingsGenerator.generateNetworkSettings())
@@ -215,6 +233,9 @@ public class WireGuardAdapter {
215233
workQueue.async {
216234
switch self.state {
217235
case .started(let handle, _):
236+
if let wgTunNameFile = self.wgTunNameFile {
237+
_ = FileManager.deleteFile(at: wgTunNameFile)
238+
}
218239
wgTurnOff(handle)
219240

220241
case .temporaryShutdown:

Sources/WireGuardKitGo/api-apple.go

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import "C"
1616
import (
1717
"fmt"
1818
"math"
19+
"net"
1920
"os"
2021
"os/signal"
2122
"runtime"
@@ -27,6 +28,7 @@ import (
2728
"golang.org/x/sys/unix"
2829
"golang.zx2c4.com/wireguard/conn"
2930
"golang.zx2c4.com/wireguard/device"
31+
"golang.zx2c4.com/wireguard/ipc"
3032
"golang.zx2c4.com/wireguard/tun"
3133
)
3234

@@ -54,6 +56,7 @@ func (l CLogger) Printf(format string, args ...interface{}) {
5456
type tunnelHandle struct {
5557
*device.Device
5658
*device.Logger
59+
uapi net.Listener
5760
}
5861

5962
var tunnelHandles = make(map[int32]tunnelHandle)
@@ -100,6 +103,7 @@ func wgTurnOn(settings *C.char, tunFd int32) int32 {
100103
unix.Close(dupTunFd)
101104
return -1
102105
}
106+
103107
tun, err := tun.CreateTUNFromFile(os.NewFile(uintptr(dupTunFd), "/dev/tun"), 0)
104108
if err != nil {
105109
logger.Errorf("Unable to create new tun device from fd: %v", err)
@@ -116,6 +120,21 @@ func wgTurnOn(settings *C.char, tunFd int32) int32 {
116120
return -1
117121
}
118122

123+
var uapi net.Listener
124+
if runtime.GOOS != "ios" {
125+
ifaceName, err := tun.Name()
126+
if err != nil {
127+
logger.Errorf("Unable to get interface name: %v", err)
128+
return -1
129+
}
130+
131+
uapi, err = openUapiSocket(logger, ifaceName, dev)
132+
if err != nil {
133+
logger.Errorf("Unable to listen on UAPI socket: %v", err)
134+
return -1
135+
}
136+
}
137+
119138
dev.Up()
120139
logger.Verbosef("Device started")
121140

@@ -129,18 +148,58 @@ func wgTurnOn(settings *C.char, tunFd int32) int32 {
129148
unix.Close(dupTunFd)
130149
return -1
131150
}
132-
tunnelHandles[i] = tunnelHandle{dev, logger}
151+
152+
tunnelHandles[i] = tunnelHandle{dev, logger, uapi}
153+
133154
return i
134155
}
135156

157+
func openUapiSocket(logger *device.Logger, ifaceName string, device *device.Device) (net.Listener, error) {
158+
fileUAPI, err := ipc.UAPIOpen(ifaceName)
159+
if err != nil {
160+
return nil, err
161+
}
162+
uapi, err := ipc.UAPIListen(ifaceName, fileUAPI)
163+
if err != nil {
164+
return nil, err
165+
}
166+
167+
go func() {
168+
for {
169+
conn, err := uapi.Accept()
170+
if err != nil {
171+
logger.Errorf("UAPI error: %v", err)
172+
return
173+
}
174+
go device.IpcHandle(conn)
175+
}
176+
}()
177+
178+
logger.Verbosef("UAPI listener started")
179+
180+
return uapi, nil
181+
}
182+
136183
//export wgTurnOff
137184
func wgTurnOff(tunnelHandle int32) {
185+
logger := &device.Logger{
186+
Verbosef: CLogger(0).Printf,
187+
Errorf: CLogger(1).Printf,
188+
}
189+
138190
dev, ok := tunnelHandles[tunnelHandle]
139191
if !ok {
140192
return
141193
}
142194
delete(tunnelHandles, tunnelHandle)
143195
dev.Close()
196+
197+
if dev.uapi != nil {
198+
err := dev.uapi.Close()
199+
if err != nil {
200+
logger.Errorf("Unable to close UAPI socket: %v", err)
201+
}
202+
}
144203
}
145204

146205
//export wgSetConfig

Sources/WireGuardKitGo/go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ module golang.zx2c4.com/wireguard/apple
33
go 1.17
44

55
require (
6-
golang.org/x/sys v0.5.0
6+
golang.org/x/sys v0.5.1-0.20230222185716-a3b23cc77e89
77
golang.zx2c4.com/wireguard v0.0.0-20230209153558-1e2c3e5a3c14
88
)
99

1010
require (
1111
golang.org/x/crypto v0.6.0 // indirect
12-
golang.org/x/net v0.6.0 // indirect
12+
golang.org/x/net v0.7.0 // indirect
1313
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
1414
)

Sources/WireGuardKitGo/go.sum

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
174174
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
175175
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
176176
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
177+
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
177178
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
178179
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
179180
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@@ -350,7 +351,6 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
350351
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
351352
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
352353
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
353-
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
354354
golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
355355
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
356356
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -425,11 +425,10 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY
425425
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
426426
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
427427
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
428-
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
429-
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
430428
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
431-
golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q=
432429
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
430+
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
431+
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
433432
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
434433
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
435434
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -500,12 +499,12 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc
500499
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
501500
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
502501
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
503-
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
504502
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
505503
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
506504
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
507-
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
508505
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
506+
golang.org/x/sys v0.5.1-0.20230222185716-a3b23cc77e89 h1:260HNjMTPDya+jq5AM1zZLgG9pv9GASPAGiEEJUbRg4=
507+
golang.org/x/sys v0.5.1-0.20230222185716-a3b23cc77e89/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
509508
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
510509
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
511510
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@@ -521,6 +520,7 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
521520
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
522521
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
523522
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
523+
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
524524
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
525525
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
526526
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -575,11 +575,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
575575
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
576576
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
577577
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
578-
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
579578
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg=
580579
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
581-
golang.zx2c4.com/wireguard v0.0.0-20230209153558-1e2c3e5a3c14 h1:HVTnb30bngAvlUMb5VRy4jELMvWL5VIapumjqzFXMZc=
582-
golang.zx2c4.com/wireguard v0.0.0-20230209153558-1e2c3e5a3c14/go.mod h1:whfbyDBt09xhCYQWtO2+3UVjlaq6/9hDZrjg2ZE6SyA=
583580
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
584581
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
585582
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
@@ -683,6 +680,7 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
683680
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
684681
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
685682
gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
683+
gvisor.dev/gvisor v0.0.0-20221203005347-703fd9b7fbc0 h1:Wobr37noukisGxpKo5jAsLREcpj61RxrWYzD8uwveOY=
686684
gvisor.dev/gvisor v0.0.0-20221203005347-703fd9b7fbc0/go.mod h1:Dn5idtptoW1dIos9U6A2rpebLs/MtTwFacjKb8jLdQA=
687685
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
688686
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

0 commit comments

Comments
 (0)