|
@@ -0,0 +1,184 @@
|
|
|
+import Foundation
|
|
|
+import Network
|
|
|
+import Security
|
|
|
+import CryptoKit
|
|
|
+
|
|
|
+/// SoftEtherProtocol manages the communication between iOS client and SoftEther VPN server
|
|
|
+class SoftEtherProtocol {
|
|
|
+
|
|
|
+ // MARK: - Properties
|
|
|
+
|
|
|
+ private var secureConnection: SecureConnection?
|
|
|
+ private var isConnected = false
|
|
|
+ private var host: String = ""
|
|
|
+ private var port: UInt16 = 443
|
|
|
+ private var nextPacketId: UInt32 = 1
|
|
|
+
|
|
|
+ // MARK: - Public Methods
|
|
|
+
|
|
|
+ /// Connect to a SoftEther VPN server
|
|
|
+ /// - Parameters:
|
|
|
+ /// - host: The server hostname or IP address
|
|
|
+ /// - port: The server port (default: 443)
|
|
|
+ /// - completion: Callback with connection result
|
|
|
+ public func connect(to host: String, port: UInt16 = 443, completion: @escaping (Bool, Error?) -> Void) {
|
|
|
+ self.host = host
|
|
|
+ self.port = port
|
|
|
+
|
|
|
+ // Create a secure connection
|
|
|
+ secureConnection = SecureConnection(host: host, port: port)
|
|
|
+
|
|
|
+ // Connect using TLS
|
|
|
+ secureConnection?.connect { [weak self] success, error in
|
|
|
+ guard let self = self, success else {
|
|
|
+ completion(false, error ?? NSError(domain: "SoftEtherError", code: 1, userInfo: [NSLocalizedDescriptionKey: "TLS connection failed"]))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // After successful TLS connection, send the client signature
|
|
|
+ self.sendClientSignature { success, error in
|
|
|
+ if success {
|
|
|
+ self.isConnected = true
|
|
|
+ }
|
|
|
+ completion(success, error)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Disconnect from the server
|
|
|
+ public func disconnect() {
|
|
|
+ secureConnection?.disconnect()
|
|
|
+ isConnected = false
|
|
|
+ }
|
|
|
+
|
|
|
+ // MARK: - Private Methods
|
|
|
+
|
|
|
+ /// Send the SoftEther client signature to identify as a legitimate client
|
|
|
+ /// - Parameter completion: Callback with result
|
|
|
+ private func sendClientSignature(completion: @escaping (Bool, Error?) -> Void) {
|
|
|
+ // Generate client signature using our specialized class
|
|
|
+ let signatureData = SoftEtherClientSignature.generateSignature()
|
|
|
+
|
|
|
+ // Create a packet with the signature data
|
|
|
+ let packetId = self.nextPacketId
|
|
|
+ self.nextPacketId += 1
|
|
|
+
|
|
|
+ let packet = SoftEtherPacket(type: 0x01, id: packetId, data: signatureData)
|
|
|
+ let packetData = packet.serialize()
|
|
|
+
|
|
|
+ print("Sending client signature packet: \(packetData.count) bytes")
|
|
|
+
|
|
|
+ // Send the packet
|
|
|
+ secureConnection?.send(data: packetData) { [weak self] error in
|
|
|
+ guard let self = self else { return }
|
|
|
+
|
|
|
+ if let error = error {
|
|
|
+ print("Error sending client signature: \(error)")
|
|
|
+ completion(false, error)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // After sending signature, wait for server response
|
|
|
+ self.receiveServerResponse { success, error in
|
|
|
+ completion(success, error)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Receive and process server response after sending signature
|
|
|
+ /// - Parameter completion: Callback with result
|
|
|
+ private func receiveServerResponse(completion: @escaping (Bool, Error?) -> Void) {
|
|
|
+ secureConnection?.receive { data, error in
|
|
|
+ if let error = error {
|
|
|
+ print("Error receiving server response: \(error)")
|
|
|
+ completion(false, error)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ guard let data = data, data.count > 4 else {
|
|
|
+ let error = NSError(domain: "SoftEtherError", code: 2, userInfo: [NSLocalizedDescriptionKey: "Invalid server response"])
|
|
|
+ print("Invalid server response: insufficient data")
|
|
|
+ completion(false, error)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ print("Received server response: \(data.count) bytes")
|
|
|
+
|
|
|
+ // Parse the response packet
|
|
|
+ guard let packet = SoftEtherPacket(fromData: data) else {
|
|
|
+ let error = NSError(domain: "SoftEtherError", code: 3, userInfo: [NSLocalizedDescriptionKey: "Invalid packet format"])
|
|
|
+ print("Could not parse server response packet")
|
|
|
+ completion(false, error)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // Verify the response
|
|
|
+ let packetData = packet.getData()
|
|
|
+ let isValid = SoftEtherClientSignature.verifyServerResponse(packetData)
|
|
|
+
|
|
|
+ if isValid {
|
|
|
+ print("Server accepted our client signature")
|
|
|
+ completion(true, nil)
|
|
|
+ } else {
|
|
|
+ print("Server rejected our client signature")
|
|
|
+ let error = NSError(domain: "SoftEtherError", code: 4, userInfo: [NSLocalizedDescriptionKey: "Server rejected client signature"])
|
|
|
+ completion(false, error)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Send a data packet to the server
|
|
|
+ /// - Parameters:
|
|
|
+ /// - data: Data to send
|
|
|
+ /// - completion: Callback with result
|
|
|
+ func sendData(data: Data, completion: @escaping (Bool, Error?) -> Void) {
|
|
|
+ guard isConnected else {
|
|
|
+ completion(false, NSError(domain: "SoftEtherError", code: 5, userInfo: [NSLocalizedDescriptionKey: "Not connected to server"]))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ let packetId = self.nextPacketId
|
|
|
+ self.nextPacketId += 1
|
|
|
+
|
|
|
+ let packet = SoftEtherPacket(type: 0x05, id: packetId, data: data)
|
|
|
+ let packetData = packet.serialize()
|
|
|
+
|
|
|
+ secureConnection?.send(data: packetData) { error in
|
|
|
+ if let error = error {
|
|
|
+ completion(false, error)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ completion(true, nil)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Receive data from the server
|
|
|
+ /// - Parameter completion: Callback with received data and result
|
|
|
+ func receiveData(completion: @escaping (Data?, Bool, Error?) -> Void) {
|
|
|
+ guard isConnected else {
|
|
|
+ completion(nil, false, NSError(domain: "SoftEtherError", code: 5, userInfo: [NSLocalizedDescriptionKey: "Not connected to server"]))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ secureConnection?.receive { data, error in
|
|
|
+ if let error = error {
|
|
|
+ completion(nil, false, error)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ guard let data = data, data.count > 4 else {
|
|
|
+ completion(nil, false, NSError(domain: "SoftEtherError", code: 2, userInfo: [NSLocalizedDescriptionKey: "Invalid server response"]))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // Parse the packet
|
|
|
+ guard let packet = SoftEtherPacket(fromData: data) else {
|
|
|
+ completion(nil, false, NSError(domain: "SoftEtherError", code: 3, userInfo: [NSLocalizedDescriptionKey: "Invalid packet format"]))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ completion(packet.getData(), true, nil)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|