Click here to Skip to main content
16,017,881 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
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)?) {
        // Add code here to handle the message.
        if let handler = completionHandler {
            handler(messageData)
        }
    }
    
    override func sleep(completionHandler: @escaping () -> Void) {
        // Add code here to get ready to sleep.
        completionHandler()
    }
    
    override func wake() {
        // Add code here to wake up.
    }
    
    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.ipv6Settings?.includedRoutes = [NEIPv6Route.`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.
Posted

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900