summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--ios/MullvadREST/ShadowSocksProxy.swift62
-rw-r--r--ios/MullvadREST/URLSessionTransport.swift30
-rw-r--r--ios/MullvadREST/shadowsocks-proxy/include/shadowsocks.h5
-rw-r--r--ios/MullvadREST/shadowsocks-proxy/src/bin/run.rs7
-rw-r--r--ios/MullvadREST/shadowsocks-proxy/src/bin/run_unsafe.rs7
-rw-r--r--ios/MullvadREST/shadowsocks-proxy/src/ffi.rs30
-rw-r--r--ios/MullvadREST/shadowsocks-proxy/src/lib.rs25
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj8
-rw-r--r--ios/MullvadVPN/AppDelegate.swift3
-rw-r--r--ios/MullvadVPN/TransportMonitor/TransportMonitor.swift12
-rw-r--r--ios/PacketTunnel/PacketTunnelProvider.swift3
-rw-r--r--ios/PacketTunnel/TunnelTransportProvider.swift7
12 files changed, 132 insertions, 67 deletions
diff --git a/ios/MullvadREST/ShadowSocksProxy.swift b/ios/MullvadREST/ShadowSocksProxy.swift
index a905cdc9c7..8c54a101ee 100644
--- a/ios/MullvadREST/ShadowSocksProxy.swift
+++ b/ios/MullvadREST/ShadowSocksProxy.swift
@@ -10,19 +10,31 @@ import Foundation
import Network
import Shadowsocks
-public class ShadowSocksProxy {
+/// A Swift wrapper around a Rust implementation of Shadowsocks proxy instance
+public class ShadowsocksProxy {
private var proxyConfig: ProxyHandle
- private let remoteAddress: IPAddress
- private let remotePort: UInt16
+ private let forwardAddress: IPAddress
+ private let forwardPort: UInt16
+ private let bridgeAddress: IPAddress
+ private let bridgePort: UInt16
private let password: String
private let cipher: String
private var didStart = false
private let stateLock = NSLock()
- public init(remoteAddress: IPAddress, remotePort: UInt16, password: String, cipher: String) {
+ public init(
+ forwardAddress: IPAddress,
+ forwardPort: UInt16,
+ bridgeAddress: IPAddress,
+ bridgePort: UInt16,
+ password: String,
+ cipher: String
+ ) {
proxyConfig = ProxyHandle(context: nil, port: 0)
- self.remoteAddress = remoteAddress
- self.remotePort = remotePort
+ self.forwardAddress = forwardAddress
+ self.forwardPort = forwardPort
+ self.bridgeAddress = bridgeAddress
+ self.bridgePort = bridgePort
self.password = password
self.cipher = cipher
}
@@ -47,25 +59,21 @@ public class ShadowSocksProxy {
guard didStart == false else { return }
didStart = true
- // Get the raw bytes of `addr.rawValue`
- remoteAddress.rawValue.withUnsafeBytes { unsafeAddressPointer in
-
- // Rebind the raw bytes to an array of bytes, and get a pointer to its beginning
- let rawAddr = unsafeAddressPointer.bindMemory(to: UInt8.self).baseAddress
-
- // Get the raw bytes access to `proxyConfig`
- _ = withUnsafeMutablePointer(to: &proxyConfig) { config in
- start_shadowsocks_proxy(
- rawAddr,
- UInt(remoteAddress.rawValue.count),
- remotePort,
- password,
- UInt(password.count),
- cipher,
- UInt(cipher.count),
- config
- )
- }
+ // Get the raw bytes access to `proxyConfig`
+ _ = withUnsafeMutablePointer(to: &proxyConfig) { config in
+ start_shadowsocks_proxy(
+ forwardAddress.rawValue.map { $0 },
+ UInt(forwardAddress.rawValue.count),
+ forwardPort,
+ bridgeAddress.rawValue.map { $0 },
+ UInt(bridgeAddress.rawValue.count),
+ bridgePort,
+ password,
+ UInt(password.count),
+ cipher,
+ UInt(cipher.count),
+ config
+ )
}
}
@@ -76,8 +84,8 @@ public class ShadowSocksProxy {
guard didStart == true else { return }
didStart = false
- _ = withUnsafePointer(to: proxyConfig) { pointer in
- stop_shadowsocks_proxy(UnsafeMutablePointer(mutating: pointer))
+ _ = withUnsafeMutablePointer(to: &proxyConfig) { config in
+ stop_shadowsocks_proxy(config)
}
}
}
diff --git a/ios/MullvadREST/URLSessionTransport.swift b/ios/MullvadREST/URLSessionTransport.swift
index 0bb765c686..0be25162a4 100644
--- a/ios/MullvadREST/URLSessionTransport.swift
+++ b/ios/MullvadREST/URLSessionTransport.swift
@@ -34,22 +34,32 @@ extension REST {
}
public final class URLSessionShadowSocksTransport: RESTTransport {
+ /// The Shadowsocks proxy instance that proxies all the traffic it receives
+ private let shadowSocksProxy: ShadowsocksProxy
+ /// The IPv4 representation of the loopback address used by `shadowSocksProxy`
+ private let localhost = "127.0.0.1"
+
+ /// The `URLSession` used to send requests via `shadowSocksProxy`
+ public let urlSession: URLSession
+
public var name: String {
return "shadow-socks-url-session"
}
- public let urlSession: URLSession
- private let shadowSocksProxy: ShadowSocksProxy
-
public init(
urlSession: URLSession,
shadowSocksConfiguration: ServerShadowsocks,
- shadowSocksBridgeRelay: BridgeRelay
+ shadowSocksBridgeRelay: BridgeRelay,
+ addressCache: REST.AddressCache
) {
self.urlSession = urlSession
- shadowSocksProxy = ShadowSocksProxy(
- remoteAddress: shadowSocksBridgeRelay.ipv4AddrIn,
- remotePort: shadowSocksConfiguration.port,
+ let apiAddress = addressCache.getCurrentEndpoint()
+
+ shadowSocksProxy = ShadowsocksProxy(
+ forwardAddress: apiAddress.ip,
+ forwardPort: apiAddress.port,
+ bridgeAddress: shadowSocksBridgeRelay.ipv4AddrIn,
+ bridgePort: shadowSocksConfiguration.port,
password: shadowSocksConfiguration.password,
cipher: shadowSocksConfiguration.cipher
)
@@ -59,14 +69,14 @@ extension REST {
_ request: URLRequest,
completion: @escaping (Data?, URLResponse?, Swift.Error?) -> Void
) -> Cancellable {
- // Start the shadow socks proxy in order to get a local port
+ // Start the Shadowsocks proxy in order to get a local port
shadowSocksProxy.start()
- // Copy the URL request and rewrite the host and port to point to the shadow socks proxy instance
+ // Copy the URL request and rewrite the host and port to point to the Shadowsocks proxy instance
var urlRequestCopy = request
urlRequestCopy.url = request.url.flatMap { url in
var components = URLComponents(url: url, resolvingAgainstBaseURL: false)
- components?.host = "127.0.0.1"
+ components?.host = localhost
components?.port = Int(shadowSocksProxy.localPort())
return components?.url
}
diff --git a/ios/MullvadREST/shadowsocks-proxy/include/shadowsocks.h b/ios/MullvadREST/shadowsocks-proxy/include/shadowsocks.h
index 487199ecc5..1a0a856d8d 100644
--- a/ios/MullvadREST/shadowsocks-proxy/include/shadowsocks.h
+++ b/ios/MullvadREST/shadowsocks-proxy/include/shadowsocks.h
@@ -16,7 +16,10 @@ typedef struct ProxyHandle {
* `proxy_config` must be pointing to a valid memory region for the size of a `ProxyHandle`
* instance.
*/
-int32_t start_shadowsocks_proxy(const uint8_t *addr,
+int32_t start_shadowsocks_proxy(const uint8_t *forward_address,
+ uintptr_t forward_address_len,
+ uint16_t forward_port,
+ const uint8_t *addr,
uintptr_t addr_len,
uint16_t port,
const uint8_t *password,
diff --git a/ios/MullvadREST/shadowsocks-proxy/src/bin/run.rs b/ios/MullvadREST/shadowsocks-proxy/src/bin/run.rs
index 073bd9cc02..1b096a5335 100644
--- a/ios/MullvadREST/shadowsocks-proxy/src/bin/run.rs
+++ b/ios/MullvadREST/shadowsocks-proxy/src/bin/run.rs
@@ -5,8 +5,11 @@ fn main() {
let password = "mullvad";
let cipher = "aes-256-gcm";
- let (port, handle) = shadowsocks_proxy::run_forwarding_proxy(socketaddr, password, cipher)
- .expect("failed to start SOCKS proxy");
+ let forward_address = SocketAddr::from_str("45.83.223.196:443").unwrap();
+
+ let (port, handle) =
+ shadowsocks_proxy::run_forwarding_proxy(forward_address, socketaddr, password, cipher)
+ .expect("failed to start SOCKS proxy");
println!("Running proxy on port {port}");
diff --git a/ios/MullvadREST/shadowsocks-proxy/src/bin/run_unsafe.rs b/ios/MullvadREST/shadowsocks-proxy/src/bin/run_unsafe.rs
index 1a3be6d541..805d1147a4 100644
--- a/ios/MullvadREST/shadowsocks-proxy/src/bin/run_unsafe.rs
+++ b/ios/MullvadREST/shadowsocks-proxy/src/bin/run_unsafe.rs
@@ -14,6 +14,10 @@ fn main() {
let password_ptr = password.as_ptr();
let password_size = password.as_bytes().len();
+ let forward_address = Ipv4Addr::from_str("45.83.223.196").unwrap();
+ let forward_address_bytes = forward_address.octets();
+ let forward_address_ptr = forward_address_bytes.as_ptr();
+
let addr = Ipv4Addr::from_str("185.65.135.117").unwrap();
let addr_bytes = addr.octets();
let addr_ptr = addr_bytes.as_ptr();
@@ -25,6 +29,9 @@ fn main() {
let retval = unsafe {
shadowsocks_proxy::start_shadowsocks_proxy(
+ forward_address_ptr,
+ forward_address_bytes.len(),
+ 443,
addr_ptr,
addr_bytes.len(),
socketaddr.port(),
diff --git a/ios/MullvadREST/shadowsocks-proxy/src/ffi.rs b/ios/MullvadREST/shadowsocks-proxy/src/ffi.rs
index d8c575ef7e..fc083f18bf 100644
--- a/ios/MullvadREST/shadowsocks-proxy/src/ffi.rs
+++ b/ios/MullvadREST/shadowsocks-proxy/src/ffi.rs
@@ -21,6 +21,9 @@ pub struct ProxyHandle {
/// instance.
#[no_mangle]
pub unsafe extern "C" fn start_shadowsocks_proxy(
+ forward_address: *const u8,
+ forward_address_len: usize,
+ forward_port: u16,
addr: *const u8,
addr_len: usize,
port: u16,
@@ -37,13 +40,23 @@ pub unsafe extern "C" fn start_shadowsocks_proxy(
.init();
});
+ let forward_ip = if let Some(forward_address) =
+ unsafe { parse_ip_addr(forward_address, forward_address_len) }
+ {
+ forward_address
+ } else {
+ return -1;
+ };
+
+ let forward_socket_addr = SocketAddr::new(forward_ip, forward_port);
+
let bridge_ip = if let Some(addr) = unsafe { parse_ip_addr(addr, addr_len) } {
addr
} else {
return -1;
};
- let bridge_addr = SocketAddr::new(bridge_ip, port);
+ let bridge_socket_addr = SocketAddr::new(bridge_ip, port);
let password = if let Some(password) = unsafe { parse_str(password, password_len) } {
password
@@ -57,13 +70,14 @@ pub unsafe extern "C" fn start_shadowsocks_proxy(
return -1;
};
- let (port, handle) = match run_forwarding_proxy(bridge_addr, &password, &cipher) {
- Ok((port, handle)) => (port, handle),
- Err(err) => {
- log::error!("Failed to run HTTP proxy {}", err);
- return err.raw_os_error().unwrap_or(-1);
- }
- };
+ let (port, handle) =
+ match run_forwarding_proxy(forward_socket_addr, bridge_socket_addr, &password, &cipher) {
+ Ok((port, handle)) => (port, handle),
+ Err(err) => {
+ log::error!("Failed to run HTTP proxy {}", err);
+ return err.raw_os_error().unwrap_or(-1);
+ }
+ };
let handle = Box::new(handle);
unsafe {
diff --git a/ios/MullvadREST/shadowsocks-proxy/src/lib.rs b/ios/MullvadREST/shadowsocks-proxy/src/lib.rs
index 66398cb9eb..3388280782 100644
--- a/ios/MullvadREST/shadowsocks-proxy/src/lib.rs
+++ b/ios/MullvadREST/shadowsocks-proxy/src/lib.rs
@@ -16,11 +16,13 @@ mod ffi;
pub use ffi::{start_shadowsocks_proxy, stop_shadowsocks_proxy, ProxyHandle};
pub fn run_forwarding_proxy(
- bridge_addr: SocketAddr,
+ forward_socket_addr: SocketAddr,
+ bridge_socket_addr: SocketAddr,
password: &str,
cipher: &str,
) -> io::Result<(u16, ShadowsocksHandle)> {
- let runtime = ShadowsocksRuntime::new(bridge_addr, password, cipher)?;
+ let runtime =
+ ShadowsocksRuntime::new(forward_socket_addr, bridge_socket_addr, password, cipher)?;
let port = runtime.port();
let handle = runtime.run()?;
@@ -46,12 +48,18 @@ impl ShadowsocksHandle {
}
impl ShadowsocksRuntime {
- pub fn new(bridge_addr: SocketAddr, password: &str, cipher: &str) -> io::Result<Self> {
+ pub fn new(
+ forward_socket_addr: SocketAddr,
+ bridge_socket_addr: SocketAddr,
+ password: &str,
+ cipher: &str,
+ ) -> io::Result<Self> {
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()?;
- let (config, local_port) = Self::create_config(bridge_addr, password, cipher)?;
+ let (config, local_port) =
+ Self::create_config(forward_socket_addr, bridge_socket_addr, password, cipher)?;
Ok(Self {
runtime,
config,
@@ -118,7 +126,8 @@ impl ShadowsocksRuntime {
}
pub fn create_config(
- bridge_addr: SocketAddr,
+ forward_socket_addr: SocketAddr,
+ bridge_socket_addr: SocketAddr,
password: &str,
cipher: &str,
) -> io::Result<(Config, u16)> {
@@ -127,9 +136,7 @@ impl ShadowsocksRuntime {
let bind_addr = SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), free_port);
let mut local_config = LocalConfig::new_with_addr(bind_addr.into(), ProtocolType::Tunnel);
- local_config.forward_addr =
- // TODO: Remove hardcoded API address
- Some(SocketAddr::new(IpAddr::V4(Ipv4Addr::new(45, 83, 223, 196)), 443).into());
+ local_config.forward_addr = Some(forward_socket_addr.into());
cfg.local = vec![LocalInstanceConfig::with_local_config(local_config)];
let cipher = match CipherKind::from_str(cipher) {
@@ -142,7 +149,7 @@ impl ShadowsocksRuntime {
}
};
let server_config = ServerInstanceConfig::with_server_config(ServerConfig::new(
- bridge_addr,
+ bridge_socket_addr,
password,
cipher,
));
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index 57a6c6f324..b700a6199f 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -7,7 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
- 01F1FF1C29F06124007083C3 /* ShadowSocksProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01F1FF1B29F06124007083C3 /* ShadowSocksProxy.swift */; };
+ 01F1FF1C29F06124007083C3 /* ShadowsocksProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01F1FF1B29F06124007083C3 /* ShadowsocksProxy.swift */; };
01F1FF1E29F0627D007083C3 /* libshadowsocks_proxy.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 01F1FF1D29F0627D007083C3 /* libshadowsocks_proxy.a */; };
062B45A328FD4CA700746E77 /* le_root_cert.cer in Resources */ = {isa = PBXBuildFile; fileRef = 06799AB428F98CE700ACD94E /* le_root_cert.cer */; };
062B45AE28FD503000746E77 /* WireGuardKit in Frameworks */ = {isa = PBXBuildFile; productRef = 062B45AD28FD503000746E77 /* WireGuardKit */; };
@@ -638,7 +638,7 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
- 01F1FF1B29F06124007083C3 /* ShadowSocksProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShadowSocksProxy.swift; sourceTree = "<group>"; };
+ 01F1FF1B29F06124007083C3 /* ShadowsocksProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShadowsocksProxy.swift; sourceTree = "<group>"; };
01F1FF1D29F0627D007083C3 /* libshadowsocks_proxy.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libshadowsocks_proxy.a; path = ../target/debug/libshadowsocks_proxy.a; sourceTree = "<group>"; };
062B45BB28FD8C3B00746E77 /* RESTDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RESTDefaults.swift; sourceTree = "<group>"; };
063687AF28EB083800BE7161 /* ProxyURLRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProxyURLRequest.swift; sourceTree = "<group>"; };
@@ -1179,8 +1179,8 @@
06FAE66528F83CA30033DD93 /* RESTURLSession.swift */,
06FAE67728F83CA40033DD93 /* ServerRelaysResponse.swift */,
06FAE66B28F83CA30033DD93 /* SSLPinningURLSessionDelegate.swift */,
+ 01F1FF1B29F06124007083C3 /* ShadowsocksProxy.swift */,
06FAE67C28F83CA50033DD93 /* URLSessionTransport.swift */,
- 01F1FF1B29F06124007083C3 /* ShadowSocksProxy.swift */,
);
path = MullvadREST;
sourceTree = "<group>";
@@ -2566,7 +2566,7 @@
06799AEA28F98E4800ACD94E /* RESTProxy.swift in Sources */,
06799ADD28F98E4800ACD94E /* RESTError.swift in Sources */,
06799ADB28F98E4800ACD94E /* RESTProxyFactory.swift in Sources */,
- 01F1FF1C29F06124007083C3 /* ShadowSocksProxy.swift in Sources */,
+ 01F1FF1C29F06124007083C3 /* ShadowsocksProxy.swift in Sources */,
06799AF228F98E4800ACD94E /* RESTAccessTokenManager.swift in Sources */,
06799AF328F98E4800ACD94E /* RESTAuthenticationProxy.swift in Sources */,
06799AE628F98E4800ACD94E /* ServerRelaysResponse.swift in Sources */,
diff --git a/ios/MullvadVPN/AppDelegate.swift b/ios/MullvadVPN/AppDelegate.swift
index 087d7142bc..b5ee97034d 100644
--- a/ios/MullvadVPN/AppDelegate.swift
+++ b/ios/MullvadVPN/AppDelegate.swift
@@ -95,7 +95,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
transportMonitor = TransportMonitor(
tunnelManager: tunnelManager,
tunnelStore: tunnelStore,
- relayCacheTracker: relayCacheTracker
+ relayCacheTracker: relayCacheTracker,
+ addressCache: addressCache
)
#if targetEnvironment(simulator)
diff --git a/ios/MullvadVPN/TransportMonitor/TransportMonitor.swift b/ios/MullvadVPN/TransportMonitor/TransportMonitor.swift
index c700f69b14..710a890e6a 100644
--- a/ios/MullvadVPN/TransportMonitor/TransportMonitor.swift
+++ b/ios/MullvadVPN/TransportMonitor/TransportMonitor.swift
@@ -18,15 +18,22 @@ final class TransportMonitor: RESTTransportProvider {
private let urlSessionTransport: REST.URLSessionTransport
private let relayCacheTracker: RelayCacheTracker
private let logger = Logger(label: "TransportMonitor")
+ private let addressCache: REST.AddressCache
// MARK: -
// MARK: Public API
- init(tunnelManager: TunnelManager, tunnelStore: TunnelStore, relayCacheTracker: RelayCacheTracker) {
+ init(
+ tunnelManager: TunnelManager,
+ tunnelStore: TunnelStore,
+ relayCacheTracker: RelayCacheTracker,
+ addressCache: REST.AddressCache
+ ) {
self.tunnelManager = tunnelManager
self.tunnelStore = tunnelStore
self.relayCacheTracker = relayCacheTracker
+ self.addressCache = addressCache
urlSessionTransport = REST.URLSessionTransport(urlSession: REST.makeURLSession())
}
@@ -54,7 +61,8 @@ final class TransportMonitor: RESTTransportProvider {
let transport = REST.URLSessionShadowSocksTransport(
urlSession: shadowSocksURLSession,
shadowSocksConfiguration: shadowSocksConfiguration,
- shadowSocksBridgeRelay: shadowSocksBridgeRelay
+ shadowSocksBridgeRelay: shadowSocksBridgeRelay,
+ addressCache: addressCache
)
shadowSocksTransport = transport
diff --git a/ios/PacketTunnel/PacketTunnelProvider.swift b/ios/PacketTunnel/PacketTunnelProvider.swift
index bca20bfed9..d58b4e0e51 100644
--- a/ios/PacketTunnel/PacketTunnelProvider.swift
+++ b/ios/PacketTunnel/PacketTunnelProvider.swift
@@ -154,7 +154,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate {
let urlSessionTransport = REST.URLSessionTransport(urlSession: urlSession)
let transportProvider = TunnelTransportProvider(
urlSessionTransport: urlSessionTransport,
- relayCache: relayCache
+ relayCache: relayCache,
+ addressCache: addressCache
)
let proxyFactory = REST.ProxyFactory.makeProxyFactory(
diff --git a/ios/PacketTunnel/TunnelTransportProvider.swift b/ios/PacketTunnel/TunnelTransportProvider.swift
index a0f7e275ff..417f6904ff 100644
--- a/ios/PacketTunnel/TunnelTransportProvider.swift
+++ b/ios/PacketTunnel/TunnelTransportProvider.swift
@@ -16,10 +16,12 @@ final class TunnelTransportProvider: RESTTransportProvider {
private let urlSessionTransport: REST.URLSessionTransport
private let relayCache: RelayCache
private let logger = Logger(label: "TunnelTransportProvider")
+ private let addressCache: REST.AddressCache
- init(urlSessionTransport: REST.URLSessionTransport, relayCache: RelayCache) {
+ init(urlSessionTransport: REST.URLSessionTransport, relayCache: RelayCache, addressCache: REST.AddressCache) {
self.urlSessionTransport = urlSessionTransport
self.relayCache = relayCache
+ self.addressCache = addressCache
}
func transport() -> MullvadREST.RESTTransport? {
@@ -43,7 +45,8 @@ final class TunnelTransportProvider: RESTTransportProvider {
let shadowSocksTransport = REST.URLSessionShadowSocksTransport(
urlSession: shadowSocksURLSession,
shadowSocksConfiguration: shadowSocksConfiguration,
- shadowSocksBridgeRelay: shadowSocksBridgeRelay
+ shadowSocksBridgeRelay: shadowSocksBridgeRelay,
+ addressCache: addressCache
)
return shadowSocksTransport