We've developed trojanVPN based on tun2socks and used tun2socks library.
This is source code of VPNManager.swift
import Foundation
import NetworkExtension
extension NEVPNStatus: CustomStringConvertible {
public var description: String {
switch self {
case .disconnected: return "Disconnected"
case .invalid: return "Invalid"
case .connected: return "Connected"
case .connecting: return "Connecting"
case .disconnecting: return "Disconnecting"
case .reasserting: return "Reasserting"
default: return "Error"
}
}
}
public class VPNManager {
public var manager = NEVPNManager.shared()
private static var sharedVPNManager: VPNManager = {
return VPNManager()
}()
public class func shared() -> VPNManager {
return sharedVPNManager
}
public init() {}
public func loadVPNPreference(completion: @escaping (Error?) -> Void) {
NETunnelProviderManager.loadAllFromPreferences() { managers, error in
guard let managers = managers, error == nil else {
completion(error)
return
}
if managers.count == 0 {
let newManager = NETunnelProviderManager()
let tunnelProtocol = NETunnelProviderProtocol()
tunnelProtocol.serverAddress = "127.0.0.1"
tunnelProtocol.providerBundleIdentifier = "io.trojanGFW.library.PacketTunnel"
tunnelProtocol.disconnectOnSleep = false
newManager.protocolConfiguration = tunnelProtocol
newManager.localizedDescription = "trojan-vpn"
newManager.isEnabled = true
newManager.saveToPreferences { error in
guard error == nil else {
completion(error)
return
}
newManager.loadFromPreferences { error in
self.manager = newManager
completion(nil)
}
}
} else {
self.manager = managers[0]
completion(nil)
}
}
}
public func enableVPNManager(completion: @escaping (Error?) -> Void) {
manager.isEnabled = true
manager.saveToPreferences { error in
guard error == nil else {
completion(error)
return
}
self.manager.loadFromPreferences { error in
completion(error)
}
}
}
public func toggleVPNConnection(completion: @escaping (Error?) -> Void) {
if self.manager.connection.status == .disconnected || self.manager.connection.status == .invalid {
do {
try self.manager.connection.startVPNTunnel()
} catch {
completion(error)
}
} else {
self.manager.connection.stopVPNTunnel()
}
}
}
This is PacketTunnelProvider.swift
import NetworkExtension
import ProxyConfig
class PacketTunnelProvider: NEPacketTunnelProvider {
var proxyClient: TrojanProxy!
override func startTunnel(options: [String : NSObject]?, completionHandler: @escaping (Error?) -> Void) {
let tunnelNetworkSettings = createTunnelSettings()
setTunnelNetworkSettings(tunnelNetworkSettings) { [weak self] error in
let tunFd = self?.packetFlow.value(forKeyPath: "socket.fileDescriptor") as! Int32
switch ProxyConfig.preferHandler {
case .Socks5:
let host = ProxyConfig.getStringConfig(name: ProxyConfig.ConfigKey.Host.rawValue)!
let port = ProxyConfig.getIntConfig(name: ProxyConfig.ConfigKey.Port.rawValue)!
let password = ProxyConfig.getStringConfig(name: ProxyConfig.ConfigKey.Password.rawValue)!
let proxyServer = "127.0.0.1:1080"
self?.proxyClient = TrojanProxy(local_host: "127.0.0.1", local_port: 1080, remote_host: host, remote_port: UInt16(port), password: password)
self?.proxyClient.start()
NSLog("proxy server \(proxyServer)")
DispatchQueue.global(qos: .default).async {
run(tunFd, "socks", proxyServer, "", "")
}
break
}
NSLog("tunnel start")
completionHandler(nil)
}
}
override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
NSLog("tunnel stop")
completionHandler()
if (proxyClient != nil) {
proxyClient.stop()
}
}
override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)?) {
if let handler = completionHandler {
handler(messageData)
}
}
override func sleep(completionHandler: @escaping () -> Void) {
completionHandler()
}
override func wake() {
}
func createTunnelSettings() -> NEPacketTunnelNetworkSettings {
let newSettings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "240.0.0.10")
newSettings.ipv4Settings = NEIPv4Settings(addresses: ["240.0.0.1"], subnetMasks: ["255.255.255.0"])
newSettings.ipv4Settings?.includedRoutes = [NEIPv4Route.`default`()]
newSettings.proxySettings = nil
newSettings.dnsSettings = NEDNSSettings(servers: ["8.8.8.8", "8.8.4.4"])
newSettings.mtu = 1500
return newSettings
}
}
Input host, port and password then click connect but it showing "connecting" then immediately "Disconnected".
What's the problem?
Please let me know who has best solution to connect.
What I have tried:
I've tried to change ipaddress and serveraddress and port but didn't resolve.