mirror of
https://github.com/SoftEtherVPN/SoftEtherVPN.git
synced 2025-09-20 02:09:25 +03:00
Compare commits
16 Commits
3f9c3fe2a1
...
master
Author | SHA1 | Date | |
---|---|---|---|
6c04825b46 | |||
0ec8a1ed54 | |||
2acefef41e | |||
efb04daa34 | |||
c399ce6bbe | |||
2746e8dd19 | |||
10d6efcc5e | |||
0389bfd97a | |||
12ed43f6eb | |||
d8bcb863f5 | |||
7228de494d | |||
afa848454a | |||
6f76880767 | |||
cb9ccf41a5 | |||
62c71ebe5c | |||
80bab0f7d7 |
@ -37,15 +37,18 @@ COPY --from=builder /usr/local/src/SoftEtherVPN/build/libcedar.so /usr/local/src
|
||||
|
||||
FROM base AS vpnserver
|
||||
COPY --from=builder /usr/local/src/SoftEtherVPN/build/vpnserver ./
|
||||
RUN ./vpnserver --help
|
||||
EXPOSE 443/tcp 992/tcp 1194/tcp 1194/udp 5555/tcp 500/udp 4500/udp
|
||||
CMD ["/usr/local/bin/vpnserver", "execsvc"]
|
||||
|
||||
|
||||
FROM base AS vpnclient
|
||||
COPY --from=builder /usr/local/src/SoftEtherVPN/build/vpnclient ./
|
||||
RUN ./vpnclient --help
|
||||
CMD ["/usr/local/bin/vpnclient", "execsvc"]
|
||||
|
||||
|
||||
FROM base AS vpnbridge
|
||||
COPY --from=builder /usr/local/src/SoftEtherVPN/build/vpnbridge ./
|
||||
RUN ./vpnbridge --help
|
||||
CMD ["/usr/local/bin/vpnbridge", "execsvc"]
|
@ -0,0 +1,118 @@
|
||||
import Foundation
|
||||
import Network
|
||||
import Security
|
||||
|
||||
/// SecureConnection handles the TLS connection with the SoftEther VPN server
|
||||
class SecureConnection {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
private var connection: NWConnection?
|
||||
private let host: String
|
||||
private let port: UInt16
|
||||
private let queue = DispatchQueue(label: "com.softether.connection", qos: .userInitiated)
|
||||
|
||||
// MARK: - Initialization
|
||||
|
||||
/// Initialize a secure connection
|
||||
/// - Parameters:
|
||||
/// - host: Server hostname or IP address
|
||||
/// - port: Server port number
|
||||
init(host: String, port: UInt16) {
|
||||
self.host = host
|
||||
self.port = port
|
||||
}
|
||||
|
||||
// MARK: - Public Methods
|
||||
|
||||
/// Connect to the server using TLS
|
||||
/// - Parameter completion: Callback with connection result
|
||||
func connect(completion: @escaping (Bool, Error?) -> Void) {
|
||||
let hostEndpoint = NWEndpoint.Host(host)
|
||||
let portEndpoint = NWEndpoint.Port(rawValue: port)!
|
||||
|
||||
// Create TLS parameters
|
||||
let tlsOptions = NWProtocolTLS.Options()
|
||||
|
||||
// Configure TLS for maximum compatibility with SoftEther
|
||||
let securityOptions = tlsOptions.securityProtocolOptions
|
||||
sec_protocol_options_set_tls_min_version(securityOptions, .TLSv12)
|
||||
sec_protocol_options_set_tls_max_version(securityOptions, .TLSv13)
|
||||
|
||||
// Allow all cipher suites for compatibility
|
||||
sec_protocol_options_set_cipher_suites(securityOptions, nil, 0)
|
||||
|
||||
// Disable certificate validation for initial development (ENABLE IN PRODUCTION)
|
||||
sec_protocol_options_set_verify_block(securityOptions, { (_, _, trustResult, _) in
|
||||
return true // Accept all certificates for testing
|
||||
}, queue)
|
||||
|
||||
// Create TCP options with TLS
|
||||
let tcpOptions = NWProtocolTCP.Options()
|
||||
tcpOptions.enableKeepalive = true
|
||||
tcpOptions.keepaliveIdle = 30
|
||||
|
||||
// Create connection parameters
|
||||
let parameters = NWParameters(tls: tlsOptions, tcp: tcpOptions)
|
||||
|
||||
// Create the connection
|
||||
connection = NWConnection(host: hostEndpoint, port: portEndpoint, using: parameters)
|
||||
|
||||
// Set up state handling
|
||||
connection?.stateUpdateHandler = { [weak self] state in
|
||||
switch state {
|
||||
case .ready:
|
||||
completion(true, nil)
|
||||
case .failed(let error):
|
||||
self?.disconnect()
|
||||
completion(false, error)
|
||||
case .cancelled:
|
||||
completion(false, NSError(domain: "SoftEtherError", code: 1000, userInfo: [NSLocalizedDescriptionKey: "Connection cancelled"]))
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Start the connection
|
||||
connection?.start(queue: queue)
|
||||
}
|
||||
|
||||
/// Disconnect from the server
|
||||
func disconnect() {
|
||||
connection?.cancel()
|
||||
connection = nil
|
||||
}
|
||||
|
||||
/// Send data to the server
|
||||
/// - Parameters:
|
||||
/// - data: Data to send
|
||||
/// - completion: Callback with error if any
|
||||
func send(data: Data, completion: @escaping (Error?) -> Void) {
|
||||
guard let connection = connection, connection.state == .ready else {
|
||||
completion(NSError(domain: "SoftEtherError", code: 1001, userInfo: [NSLocalizedDescriptionKey: "Connection not ready"]))
|
||||
return
|
||||
}
|
||||
|
||||
connection.send(content: data, completion: .contentProcessed { error in
|
||||
completion(error)
|
||||
})
|
||||
}
|
||||
|
||||
/// Receive data from the server
|
||||
/// - Parameter completion: Callback with received data and error if any
|
||||
func receive(completion: @escaping (Data?, Error?) -> Void) {
|
||||
guard let connection = connection, connection.state == .ready else {
|
||||
completion(nil, NSError(domain: "SoftEtherError", code: 1001, userInfo: [NSLocalizedDescriptionKey: "Connection not ready"]))
|
||||
return
|
||||
}
|
||||
|
||||
connection.receive(minimumIncompleteLength: 1, maximumLength: 65536) { data, _, isComplete, error in
|
||||
completion(data, error)
|
||||
|
||||
if isComplete {
|
||||
// Connection was closed by the peer
|
||||
self.disconnect()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
import Foundation
|
||||
|
||||
/// Handles the specific client signature format that SoftEther expects
|
||||
class SoftEtherClientSignature {
|
||||
|
||||
// MARK: - Constants
|
||||
|
||||
private enum Constants {
|
||||
static let clientBuildNumber: UInt32 = 5187
|
||||
static let clientVersion: UInt32 = 5_02_0000 + clientBuildNumber
|
||||
static let clientString = "SoftEther VPN Client"
|
||||
static let softEtherMagic: [UInt8] = [0x5E, 0x68] // 'Se' in hex
|
||||
|
||||
// Protocol identification constants from SoftEther source
|
||||
static let cedar = "CEDAR"
|
||||
static let sessionKey = "sessionkey"
|
||||
static let protocol1 = "PROTOCOL"
|
||||
static let protocol2 = "PROTOCOL2"
|
||||
}
|
||||
|
||||
// MARK: - Public Methods
|
||||
|
||||
/// Generate the client signature packet that identifies this client as a legitimate SoftEther VPN client
|
||||
/// - Returns: Data containing the formatted client signature
|
||||
static func generateSignature() -> Data {
|
||||
var data = Data()
|
||||
|
||||
// 1. Add SoftEther magic bytes
|
||||
data.append(contentsOf: Constants.softEtherMagic)
|
||||
|
||||
// 2. Add client version in network byte order (big endian)
|
||||
data.appendUInt32(Constants.clientVersion)
|
||||
|
||||
// 3. Add client build number in network byte order
|
||||
data.appendUInt32(Constants.clientBuildNumber)
|
||||
|
||||
// 4. Add cedar protocol identifier
|
||||
if let cedarData = Constants.cedar.data(using: .ascii) {
|
||||
data.append(cedarData)
|
||||
data.append(0) // null terminator
|
||||
}
|
||||
|
||||
// 5. Add client string with null terminator
|
||||
if let clientString = (Constants.clientString + "\0").data(using: .ascii) {
|
||||
data.append(clientString)
|
||||
}
|
||||
|
||||
// 6. Add protocol identifiers
|
||||
if let protocolData = (Constants.protocol1 + "\0").data(using: .ascii) {
|
||||
data.append(protocolData)
|
||||
}
|
||||
|
||||
if let protocol2Data = (Constants.protocol2 + "\0").data(using: .ascii) {
|
||||
data.append(protocol2Data)
|
||||
}
|
||||
|
||||
// 7. Add session key marker
|
||||
if let sessionKeyData = (Constants.sessionKey + "\0").data(using: .ascii) {
|
||||
data.append(sessionKeyData)
|
||||
}
|
||||
|
||||
// 8. Add random data for session key (typically 20 bytes)
|
||||
let randomSessionKey = SoftEtherCrypto.randomBytes(count: 20)
|
||||
data.append(randomSessionKey)
|
||||
|
||||
// 9. Calculate and append SHA-1 hash of the entire data for integrity verification
|
||||
let hash = SoftEtherCrypto.sha1(data)
|
||||
data.append(hash)
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
/// Verify a server response to the client signature
|
||||
/// - Parameter data: Response data from server
|
||||
/// - Returns: True if valid response, false otherwise
|
||||
static func verifyServerResponse(_ data: Data) -> Bool {
|
||||
// Basic validation - a real implementation would parse and validate the server response format
|
||||
// This is a minimal check to see if we have enough data and it starts with the magic bytes
|
||||
guard data.count >= 8 else {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check if response starts with SoftEther magic bytes
|
||||
if data[0] == Constants.softEtherMagic[0] && data[1] == Constants.softEtherMagic[1] {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
import Foundation
|
||||
import CryptoKit
|
||||
|
||||
/// Handles encryption operations for SoftEther protocol
|
||||
class SoftEtherCrypto {
|
||||
|
||||
// MARK: - Constants
|
||||
|
||||
private enum Constants {
|
||||
static let sha1Size = 20
|
||||
static let md5Size = 16
|
||||
}
|
||||
|
||||
// MARK: - Public Methods
|
||||
|
||||
/// Generate secure random bytes
|
||||
/// - Parameter count: Number of random bytes to generate
|
||||
/// - Returns: Data containing random bytes
|
||||
static func randomBytes(count: Int) -> Data {
|
||||
var data = Data(count: count)
|
||||
_ = data.withUnsafeMutableBytes {
|
||||
SecRandomCopyBytes(kSecRandomDefault, count, $0.baseAddress!)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
/// Calculate SHA-1 hash
|
||||
/// - Parameter data: Input data
|
||||
/// - Returns: SHA-1 hash of the input data
|
||||
static func sha1(_ data: Data) -> Data {
|
||||
let digest = SHA1.hash(data: data)
|
||||
return Data(digest)
|
||||
}
|
||||
|
||||
/// Calculate MD5 hash
|
||||
/// - Parameter data: Input data
|
||||
/// - Returns: MD5 hash of the input data
|
||||
static func md5(_ data: Data) -> Data {
|
||||
let digest = Insecure.MD5.hash(data: data)
|
||||
return Data(digest)
|
||||
}
|
||||
|
||||
/// Encrypt data using RC4 algorithm (for SoftEther compatibility)
|
||||
/// - Parameters:
|
||||
/// - data: Data to encrypt
|
||||
/// - key: Encryption key
|
||||
/// - Returns: Encrypted data
|
||||
static func rc4Encrypt(data: Data, key: Data) -> Data {
|
||||
let rc4 = RC4(key: key)
|
||||
return rc4.process(data)
|
||||
}
|
||||
|
||||
/// Decrypt data using RC4 algorithm (for SoftEther compatibility)
|
||||
/// - Parameters:
|
||||
/// - data: Data to decrypt
|
||||
/// - key: Decryption key
|
||||
/// - Returns: Decrypted data
|
||||
static func rc4Decrypt(data: Data, key: Data) -> Data {
|
||||
// RC4 is symmetric, so encryption and decryption are the same operation
|
||||
return rc4Encrypt(data: data, key: key)
|
||||
}
|
||||
}
|
||||
|
||||
/// Simple RC4 implementation for SoftEther compatibility
|
||||
/// Note: RC4 is considered insecure, but SoftEther uses it in parts of its protocol
|
||||
private class RC4 {
|
||||
private var state: [UInt8]
|
||||
|
||||
init(key: Data) {
|
||||
state = Array(0...255)
|
||||
var j: Int = 0
|
||||
|
||||
// Key scheduling algorithm
|
||||
for i in 0..<256 {
|
||||
let keyByte = key[i % key.count]
|
||||
j = (j + Int(state[i]) + Int(keyByte)) & 0xFF
|
||||
state.swapAt(i, j)
|
||||
}
|
||||
}
|
||||
|
||||
func process(_ data: Data) -> Data {
|
||||
var result = Data(count: data.count)
|
||||
var i: Int = 0
|
||||
var j: Int = 0
|
||||
|
||||
// Generate keystream and XOR with plaintext
|
||||
for k in 0..<data.count {
|
||||
i = (i + 1) & 0xFF
|
||||
j = (j + Int(state[i])) & 0xFF
|
||||
state.swapAt(i, j)
|
||||
let keyStreamByte = state[(Int(state[i]) + Int(state[j])) & 0xFF]
|
||||
result[k] = data[k] ^ keyStreamByte
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
123
SoftEtherVPN-iOS/SoftEtherVPN-iOS/Protocol/SoftEtherPacket.swift
Normal file
123
SoftEtherVPN-iOS/SoftEtherVPN-iOS/Protocol/SoftEtherPacket.swift
Normal file
@ -0,0 +1,123 @@
|
||||
import Foundation
|
||||
|
||||
/// Handles the SoftEther packet structure for communication
|
||||
class SoftEtherPacket {
|
||||
|
||||
// MARK: - Constants
|
||||
|
||||
private enum PacketType: UInt32 {
|
||||
case clientSignature = 0x01
|
||||
case serverResponse = 0x02
|
||||
case sessionRequest = 0x03
|
||||
case sessionResponse = 0x04
|
||||
case data = 0x05
|
||||
case keepAlive = 0x06
|
||||
}
|
||||
|
||||
private enum Constants {
|
||||
static let headerSize: UInt32 = 16
|
||||
static let maxPacketSize: UInt32 = 1024 * 1024 // 1MB
|
||||
}
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
private var packetType: PacketType
|
||||
private var packetId: UInt32
|
||||
private var packetData: Data
|
||||
|
||||
// MARK: - Initialization
|
||||
|
||||
/// Initialize a packet with type, ID and data
|
||||
/// - Parameters:
|
||||
/// - type: Packet type
|
||||
/// - id: Packet ID
|
||||
/// - data: Packet payload
|
||||
init(type: UInt32, id: UInt32, data: Data) {
|
||||
self.packetType = PacketType(rawValue: type) ?? .data
|
||||
self.packetId = id
|
||||
self.packetData = data
|
||||
}
|
||||
|
||||
/// Initialize a packet from raw data
|
||||
/// - Parameter data: Raw packet data
|
||||
init?(fromData data: Data) {
|
||||
guard data.count >= Int(Constants.headerSize) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Parse header
|
||||
let typeValue = data.readUInt32(at: 0)
|
||||
self.packetId = data.readUInt32(at: 4)
|
||||
let dataSize = data.readUInt32(at: 8)
|
||||
|
||||
// Validate packet
|
||||
guard let type = PacketType(rawValue: typeValue),
|
||||
dataSize <= Constants.maxPacketSize,
|
||||
data.count >= Int(Constants.headerSize + dataSize) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
self.packetType = type
|
||||
|
||||
// Extract payload
|
||||
let startIndex = Int(Constants.headerSize)
|
||||
let endIndex = startIndex + Int(dataSize)
|
||||
self.packetData = data.subdata(in: startIndex..<endIndex)
|
||||
}
|
||||
|
||||
// MARK: - Public Methods
|
||||
|
||||
/// Serialize the packet to binary data format
|
||||
/// - Returns: Serialized packet data
|
||||
func serialize() -> Data {
|
||||
var result = Data(capacity: Int(Constants.headerSize) + packetData.count)
|
||||
|
||||
// Write header
|
||||
result.appendUInt32(packetType.rawValue)
|
||||
result.appendUInt32(packetId)
|
||||
result.appendUInt32(UInt32(packetData.count))
|
||||
result.appendUInt32(0) // Reserved
|
||||
|
||||
// Write payload
|
||||
result.append(packetData)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/// Get the packet type
|
||||
/// - Returns: Packet type
|
||||
func getType() -> UInt32 {
|
||||
return packetType.rawValue
|
||||
}
|
||||
|
||||
/// Get the packet ID
|
||||
/// - Returns: Packet ID
|
||||
func getId() -> UInt32 {
|
||||
return packetId
|
||||
}
|
||||
|
||||
/// Get the packet payload
|
||||
/// - Returns: Packet payload data
|
||||
func getData() -> Data {
|
||||
return packetData
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Extensions
|
||||
|
||||
extension Data {
|
||||
/// Read a UInt32 value from the data at specified offset
|
||||
/// - Parameter offset: Offset to read from
|
||||
/// - Returns: UInt32 value in big-endian order
|
||||
func readUInt32(at offset: Int) -> UInt32 {
|
||||
let slice = self.subdata(in: offset..<(offset + 4))
|
||||
return slice.withUnsafeBytes { $0.load(as: UInt32.self).bigEndian }
|
||||
}
|
||||
|
||||
/// Append a UInt32 value to the data in big-endian order
|
||||
/// - Parameter value: UInt32 value to append
|
||||
mutating func appendUInt32(_ value: UInt32) {
|
||||
var bigEndian = value.bigEndian
|
||||
append(UnsafeBufferPointer(start: &bigEndian, count: 1))
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
149
SoftEtherVPN-iOS/SoftEtherVPN-iOS/SoftEtherVPNClient.swift
Normal file
149
SoftEtherVPN-iOS/SoftEtherVPN-iOS/SoftEtherVPNClient.swift
Normal file
@ -0,0 +1,149 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
/// SoftEtherVPNClient provides a simple interface for connecting to SoftEther VPN servers
|
||||
public class SoftEtherVPNClient {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
private let protocol: SoftEtherProtocol
|
||||
private var connectionState: ConnectionState = .disconnected
|
||||
|
||||
// MARK: - Public Types
|
||||
|
||||
/// Connection states for the VPN client
|
||||
public enum ConnectionState {
|
||||
case disconnected
|
||||
case connecting
|
||||
case connected
|
||||
case disconnecting
|
||||
case error(Error)
|
||||
}
|
||||
|
||||
/// Connection delegate to receive state updates
|
||||
public protocol ConnectionDelegate: AnyObject {
|
||||
func connectionStateDidChange(_ state: ConnectionState)
|
||||
}
|
||||
|
||||
/// Weak reference to the delegate
|
||||
public weak var delegate: ConnectionDelegate?
|
||||
|
||||
// MARK: - Initialization
|
||||
|
||||
public init() {
|
||||
self.protocol = SoftEtherProtocol()
|
||||
}
|
||||
|
||||
// MARK: - Public Methods
|
||||
|
||||
/// Connect to a SoftEther VPN server
|
||||
/// - Parameters:
|
||||
/// - host: Server hostname or IP address
|
||||
/// - port: Server port (default: 443)
|
||||
/// - completion: Optional completion handler
|
||||
public func connect(to host: String, port: UInt16 = 443, completion: ((Bool, Error?) -> Void)? = nil) {
|
||||
// Update state
|
||||
connectionState = .connecting
|
||||
delegate?.connectionStateDidChange(connectionState)
|
||||
|
||||
// Connect using the protocol implementation
|
||||
protocol.connect(to: host, port: port) { [weak self] success, error in
|
||||
guard let self = self else { return }
|
||||
|
||||
if success {
|
||||
self.connectionState = .connected
|
||||
} else if let error = error {
|
||||
self.connectionState = .error(error)
|
||||
} else {
|
||||
self.connectionState = .disconnected
|
||||
}
|
||||
|
||||
self.delegate?.connectionStateDidChange(self.connectionState)
|
||||
completion?(success, error)
|
||||
}
|
||||
}
|
||||
|
||||
/// Disconnect from the server
|
||||
/// - Parameter completion: Optional completion handler
|
||||
public func disconnect(completion: (() -> Void)? = nil) {
|
||||
// Update state
|
||||
connectionState = .disconnecting
|
||||
delegate?.connectionStateDidChange(connectionState)
|
||||
|
||||
// Disconnect
|
||||
protocol.disconnect()
|
||||
|
||||
// Update state again
|
||||
connectionState = .disconnected
|
||||
delegate?.connectionStateDidChange(connectionState)
|
||||
|
||||
completion?()
|
||||
}
|
||||
|
||||
/// Get the current connection state
|
||||
/// - Returns: Current ConnectionState
|
||||
public func getConnectionState() -> ConnectionState {
|
||||
return connectionState
|
||||
}
|
||||
|
||||
/// Check if currently connected
|
||||
/// - Returns: True if connected, false otherwise
|
||||
public func isConnected() -> Bool {
|
||||
if case .connected = connectionState {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// MARK: - Example Usage
|
||||
|
||||
/// Example showing how to use this class in a view controller
|
||||
public static func exampleUsage() -> String {
|
||||
return """
|
||||
// In your view controller:
|
||||
|
||||
private let vpnClient = SoftEtherVPNClient()
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Set delegate
|
||||
vpnClient.delegate = self
|
||||
}
|
||||
|
||||
@IBAction func connectButtonTapped(_ sender: UIButton) {
|
||||
if vpnClient.isConnected() {
|
||||
vpnClient.disconnect()
|
||||
} else {
|
||||
vpnClient.connect(to: "vpn.example.com") { success, error in
|
||||
if !success {
|
||||
print("Failed to connect: \\(error?.localizedDescription ?? "Unknown error")")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - ConnectionDelegate
|
||||
|
||||
extension YourViewController: SoftEtherVPNClient.ConnectionDelegate {
|
||||
func connectionStateDidChange(_ state: SoftEtherVPNClient.ConnectionState) {
|
||||
switch state {
|
||||
case .connected:
|
||||
connectButton.setTitle("Disconnect", for: .normal)
|
||||
statusLabel.text = "Connected"
|
||||
case .connecting:
|
||||
statusLabel.text = "Connecting..."
|
||||
case .disconnecting:
|
||||
statusLabel.text = "Disconnecting..."
|
||||
case .disconnected:
|
||||
connectButton.setTitle("Connect", for: .normal)
|
||||
statusLabel.text = "Disconnected"
|
||||
case .error(let error):
|
||||
statusLabel.text = "Error: \\(error.localizedDescription)"
|
||||
connectButton.setTitle("Connect", for: .normal)
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
}
|
||||
}
|
@ -125,8 +125,10 @@ if(UNIX)
|
||||
message("-- Using system's cpu_features")
|
||||
target_link_libraries(mayaqua PRIVATE cpu_features)
|
||||
else()
|
||||
message("-- Using bundled cpu_features")
|
||||
set(BUILD_SHARED_LIBS OFF)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
add_subdirectory(3rdparty/cpu_features)
|
||||
set_property(TARGET cpu_features PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
target_link_libraries(mayaqua PRIVATE cpu_features)
|
||||
endif()
|
||||
|
||||
|
@ -2057,43 +2057,15 @@ bool ParsePacketL2Ex(PKT *p, UCHAR *buf, UINT size, bool no_l3, bool no_l3_l4_ex
|
||||
|
||||
if (type_id_16 > 1500)
|
||||
{
|
||||
// Ordinary Ethernet frame
|
||||
switch (type_id_16)
|
||||
if (type_id_16 == MAC_PROTO_TAGVLAN)
|
||||
{
|
||||
case MAC_PROTO_ARPV4: // ARPv4
|
||||
if (no_l3 || no_l3_l4_except_icmpv6)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return ParsePacketARPv4(p, buf, size);
|
||||
|
||||
case MAC_PROTO_IPV4: // IPv4
|
||||
if (no_l3 || no_l3_l4_except_icmpv6)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return ParsePacketIPv4(p, buf, size);
|
||||
|
||||
case MAC_PROTO_IPV6: // IPv6
|
||||
if (no_l3)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return ParsePacketIPv6(p, buf, size, no_l3_l4_except_icmpv6);
|
||||
|
||||
default: // Unknown
|
||||
if (type_id_16 == p->VlanTypeID)
|
||||
{
|
||||
// VLAN
|
||||
return ParsePacketTAGVLAN(p, buf, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// Parse VLAN frame
|
||||
return ParsePacketTAGVLAN(p, buf, size, no_l3, no_l3_l4_except_icmpv6);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Parse Ordinary Ethernet frame
|
||||
return ParsePacketL3(p, buf, size, type_id_16, no_l3, no_l3_l4_except_icmpv6);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -2128,10 +2100,44 @@ bool ParsePacketL2Ex(PKT *p, UCHAR *buf, UINT size, bool no_l3, bool no_l3_l4_ex
|
||||
}
|
||||
}
|
||||
|
||||
bool ParsePacketL3(PKT *p, UCHAR *buf, UINT size, USHORT proto, bool no_l3, bool no_l3_l4_except_icmpv6)
|
||||
{
|
||||
switch (proto)
|
||||
{
|
||||
case MAC_PROTO_ARPV4: // ARPv4
|
||||
if (no_l3 || no_l3_l4_except_icmpv6)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return ParsePacketARPv4(p, buf, size);
|
||||
|
||||
case MAC_PROTO_IPV4: // IPv4
|
||||
if (no_l3 || no_l3_l4_except_icmpv6)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return ParsePacketIPv4(p, buf, size);
|
||||
|
||||
case MAC_PROTO_IPV6: // IPv6
|
||||
if (no_l3)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return ParsePacketIPv6(p, buf, size, no_l3_l4_except_icmpv6);
|
||||
|
||||
default: // Unknown
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// TAG VLAN parsing
|
||||
bool ParsePacketTAGVLAN(PKT *p, UCHAR *buf, UINT size)
|
||||
bool ParsePacketTAGVLAN(PKT *p, UCHAR *buf, UINT size, bool no_l3, bool no_l3_l4_except_icmpv6)
|
||||
{
|
||||
USHORT vlan_ushort;
|
||||
USHORT proto_ushort;
|
||||
// Validate arguments
|
||||
if (p == NULL || buf == NULL)
|
||||
{
|
||||
@ -2151,12 +2157,17 @@ bool ParsePacketTAGVLAN(PKT *p, UCHAR *buf, UINT size)
|
||||
buf += sizeof(TAGVLAN_HEADER);
|
||||
size -= sizeof(TAGVLAN_HEADER);
|
||||
|
||||
vlan_ushort = READ_USHORT(p->L3.TagVlanHeader->Data);
|
||||
vlan_ushort = READ_USHORT(p->L3.TagVlanHeader->TagID);
|
||||
vlan_ushort = vlan_ushort & 0xFFF;
|
||||
|
||||
p->VlanId = vlan_ushort;
|
||||
|
||||
return true;
|
||||
proto_ushort = READ_USHORT(p->L3.TagVlanHeader->Protocol);
|
||||
proto_ushort = proto_ushort & 0xFFFF;
|
||||
|
||||
|
||||
// Parse the L3 packet
|
||||
return ParsePacketL3(p, buf, size, proto_ushort, no_l3, no_l3_l4_except_icmpv6);
|
||||
}
|
||||
|
||||
// BPDU Parsing
|
||||
|
@ -87,7 +87,8 @@ struct ARPV4_HEADER
|
||||
// Tagged VLAN header
|
||||
struct TAGVLAN_HEADER
|
||||
{
|
||||
UCHAR Data[2]; // Data
|
||||
UCHAR TagID[2]; // TagID
|
||||
UCHAR Protocol[2]; // Protocol
|
||||
} GCC_PACKED;
|
||||
|
||||
// IPv4 header
|
||||
@ -762,10 +763,11 @@ void FreePacketTCPv4(PKT *p);
|
||||
void FreePacketICMPv4(PKT *p);
|
||||
void FreePacketDHCPv4(PKT *p);
|
||||
bool ParsePacketL2Ex(PKT *p, UCHAR *buf, UINT size, bool no_l3, bool no_l3_l4_except_icmpv6);
|
||||
bool ParsePacketL3(PKT *p, UCHAR *buf, UINT size, USHORT proto, bool no_l3, bool no_l3_l4_except_icmpv6);
|
||||
bool ParsePacketARPv4(PKT *p, UCHAR *buf, UINT size);
|
||||
bool ParsePacketIPv4(PKT *p, UCHAR *buf, UINT size);
|
||||
bool ParsePacketBPDU(PKT *p, UCHAR *buf, UINT size);
|
||||
bool ParsePacketTAGVLAN(PKT *p, UCHAR *buf, UINT size);
|
||||
bool ParsePacketTAGVLAN(PKT *p, UCHAR *buf, UINT size, bool no_l3, bool no_l3_l4_except_icmpv6);
|
||||
bool ParseICMPv4(PKT *p, UCHAR *buf, UINT size);
|
||||
bool ParseICMPv6(PKT *p, UCHAR *buf, UINT size);
|
||||
bool ParseTCP(PKT *p, UCHAR *buf, UINT size);
|
||||
|
@ -1336,7 +1336,7 @@ SM_FMINFO_HUB Virtual Hub #%u
|
||||
SM_FMINFO_HUB_TAG_1 %S (Dinamis)
|
||||
SM_FMINFO_HUB_TAG_2 %S (Statis)
|
||||
SM_FMINFO_NUM_SESSION Jumlah Sesi
|
||||
SM_FMINFO_NUM_CONNECTION Jumlah Koneksi TCP
|
||||
SM_FMINFO_NUN_CONNECTION Jumlah Koneksi TCP
|
||||
SM_FMINFO_CAPTION Status Anggota Cluster Server
|
||||
SM_FC_STATUS_CAPTION Status Koneksi ke Pengendali Cluster
|
||||
SM_FC_IP Alamat IP Pengendali
|
||||
@ -1890,7 +1890,7 @@ LE_RECONNECT Pengaturan EtherIP / L2TPv3 telah diubah. Pipa internal sekarang
|
||||
|
||||
|
||||
# (PPP Log)
|
||||
LP_PREFIX Sesi PPP %S[%S:%u]:
|
||||
LP_PREFIX %S%SSesi PPP [%S:%u]:
|
||||
LP_CONNECTED Sesi PPP baru dimulai (Protokol atas: %S). Alamat IP Klien PPP: %S (Nama Host: "%S"), Nomor Port Klien PPP: %u, Alamat IP Server PPP: %S, Nomor Port Server PPP: %u, Nama Perangkat Lunak Klien: "%S", Ukuran Segmen Maksimum TCP IPv4 (MSS): %u byte
|
||||
LP_DISCONNECTED Sesi PPP terputus.
|
||||
LP_PAP_REJECTED Klien menolak untuk menerima protokol otentikasi "PAP" (Protokol Otentikasi Kata Sandi, protokol otentikasi kata sandi teks jelas). Aktifkan PAP di sisi klien dan coba lagi.
|
||||
@ -4588,8 +4588,8 @@ CMD_ListenerDisable_PortPrompt Nomor port dari Listener TCP/IP yang akan dihenti
|
||||
# PortsUDPSet command
|
||||
CMD_PortsUDPSet Mengatur Port UDP yang Harus Didengarkan oleh Server
|
||||
CMD_PortsUDPSet_Help Perintah ini dapat digunakan untuk menentukan satu atau beberapa port UDP yang harus didengarkan oleh server. \nAnda dapat menentukan port yang sedang digunakan oleh proses lain, namun server tidak akan dapat menggunakannya sampai port tersebut menjadi bebas. \nTentukan nomor port yang berada dalam rentang 1 hingga 65535. \nAnda dapat melihat port yang saat ini telah disetel dengan perintah PortsUDPGet. \nUntuk menjalankan perintah ini, Anda harus memiliki hak akses administrator VPN Server.
|
||||
CMD_PortsUDPSet_Args PortsUDPSet [port]
|
||||
CMD_PortsUDPSet_[port] Beberapa port UDP dapat ditentukan dengan memisahkannya menggunakan spasi atau koma, misalnya: "443, 992, 1194, 5555". \nTentukan "0" untuk menonaktifkan pendengar UDP. \n\nPort:
|
||||
CMD_PortsUDPSet_Args PortsUDPSet [ports]
|
||||
CMD_PortsUDPSet_[ports] Beberapa port UDP dapat ditentukan dengan memisahkannya menggunakan spasi atau koma, misalnya: "443, 992, 1194, 5555". \nTentukan "0" untuk menonaktifkan pendengar UDP. \n\nPort:
|
||||
|
||||
|
||||
# PortsUDPGet command
|
||||
@ -4602,11 +4602,11 @@ CMD_PortsUDPGet_Ports Port UDP
|
||||
# ProtoOptionsSet command
|
||||
CMD_ProtoOptionsSet Mengatur nilai opsi untuk protokol yang ditentukan
|
||||
CMD_ProtoOptionsSet_Help Perintah ini dapat digunakan untuk mengubah nilai opsi untuk protokol tertentu. \nAnda dapat mengambil opsi menggunakan perintah ProtoOptionsGet. \nUntuk menjalankan perintah ini, Anda harus memiliki hak istimewa administrator VPN Server.
|
||||
CMD_ProtoOptionsSet_Args ProtoOptionsSet [protokol] [/NAME:nama_opsi] [/VALUE:string/true/false]
|
||||
CMD_ProtoOptionsSet_[protokol] Nama protokol.
|
||||
CMD_ProtoOptionsSet_Args ProtoOptionsSet [protocol] [/NAME:option_name] [/VALUE:string/true/false]
|
||||
CMD_ProtoOptionsSet_[protocol] Nama protokol.
|
||||
CMD_ProtoOptionsSet_NAME Nama opsi.
|
||||
CMD_ProtoOptionsSet_VALUE Nilai opsi. Pastikan untuk menulis nilai yang diterima oleh protokol yang ditentukan!
|
||||
CMD_ProtoOptionsSet_Prompt_[protokol] Protokol:
|
||||
CMD_ProtoOptionsSet_Prompt_[protocol] Protokol:
|
||||
CMD_ProtoOptionsSet_Prompt_NAME Opsi:
|
||||
CMD_ProtoOptionsSet_Prompt_VALUE Nilai:
|
||||
|
||||
@ -4614,9 +4614,9 @@ CMD_ProtoOptionsSet_Prompt_VALUE Nilai:
|
||||
# ProtoOptionsGet command
|
||||
CMD_ProtoOptionsGet Menampilkan opsi untuk protokol yang ditentukan
|
||||
CMD_ProtoOptionsGet_Help Perintah ini dapat digunakan untuk mengambil opsi untuk protokol tertentu. \nInformasi detail (misalnya tipe nilai) akan ditampilkan. \nAnda dapat mengubah nilai opsi dengan perintah ProtoOptionsSet.
|
||||
CMD_ProtoOptionsGet_Args ProtoOptionsGet [protokol]
|
||||
CMD_ProtoOptionsGet_[protokol] Nama protokol.
|
||||
CMD_ProtoOptionsGet_Prompt_[protokol] Protokol:
|
||||
CMD_ProtoOptionsGet_Args ProtoOptionsGet [protocol]
|
||||
CMD_ProtoOptionsGet_[protocol] Nama protokol.
|
||||
CMD_ProtoOptionsGet_Prompt_[protocol] Protokol:
|
||||
CMD_ProtoOptionsGet_Column_Name Nama
|
||||
CMD_ProtoOptionsGet_Column_Type Tipe
|
||||
CMD_ProtoOptionsGet_Column_Value Nilai
|
||||
@ -4633,8 +4633,8 @@ CMD_ProtoOptions_Description_OpenVPN_Timeout Waktu dalam milidetik setelah
|
||||
# ServerPasswordSet command
|
||||
CMD_ServerPasswordSet Setel Kata Sandi Administrator VPN Server
|
||||
CMD_ServerPasswordSet_Help Ini mengatur kata sandi administrator VPN Server. Anda dapat menentukan kata sandi sebagai parameter. Jika kata sandi tidak ditentukan, prompt akan ditampilkan untuk memasukkan kata sandi dan konfirmasi kata sandi. Jika Anda menyertakan kata sandi sebagai parameter, kata sandi ini akan ditampilkan sesaat di layar, yang dapat menimbulkan risiko. Kami menyarankan agar sebisa mungkin, hindari menentukan parameter ini dan masukkan kata sandi menggunakan prompt kata sandi. \nUntuk mengeksekusi perintah ini, Anda harus memiliki hak istimewa administrator VPN Server.
|
||||
CMD_ServerPasswordSet_Args ServerPasswordSet [kata_sandi]
|
||||
CMD_ServerPasswordSet_[kata_sandi] Ini menentukan pengaturan kata sandi baru.
|
||||
CMD_ServerPasswordSet_Args ServerPasswordSet [password]
|
||||
CMD_ServerPasswordSet_[password] Ini menentukan pengaturan kata sandi baru.
|
||||
|
||||
|
||||
# ClusterSettingGet command
|
||||
@ -5232,25 +5232,25 @@ CMD_StatusGet_Args StatusGet
|
||||
|
||||
|
||||
# LogGet command
|
||||
CMD_LogGet Dapatkan Pengaturan Penyimpanan Log dari Hub Virtual
|
||||
CMD_LogGet_Help Gunakan ini untuk mendapatkan pengaturan penyimpanan log dari Hub Virtual yang sedang dikelola. Anda dapat memperoleh informasi pengaturan seperti pengaturan penyimpanan terkait log keamanan dan log paket serta informasi tentang apa yang telah disimpan.
|
||||
CMD_LogGet_Args LogGet
|
||||
CMD_Log_Security Log Simpan Log Keamanan
|
||||
CMD_Log_PacketLog Simpan Log Paket
|
||||
CMD_Log_SwitchType Siklus Pergantian File Log
|
||||
CMD_Log_0 Log Koneksi TCP
|
||||
CMD_Log_1 Log Paket TCP
|
||||
CMD_Log_2 Log DHCP
|
||||
CMD_Log_3 Log UDP
|
||||
CMD_Log_4 Log ICMP
|
||||
CMD_Log_5 Log IP
|
||||
CMD_Log_6 Log ARP
|
||||
CMD_Log_7 Log Ethernet
|
||||
CMD_LogGet Dapatkan Pengaturan Penyimpanan Log dari Hub Virtual
|
||||
CMD_LogGet_Help Gunakan ini untuk mendapatkan pengaturan penyimpanan log dari Hub Virtual yang sedang dikelola. Anda dapat memperoleh informasi pengaturan seperti pengaturan penyimpanan terkait log keamanan dan log paket serta informasi tentang apa yang telah disimpan.
|
||||
CMD_LogGet_Args LogGet
|
||||
CMD_Log_SecurityLog Simpan Log Keamanan
|
||||
CMD_Log_PacketLog Simpan Log Paket
|
||||
CMD_Log_SwitchType Siklus Pergantian File Log
|
||||
CMD_Log_0 Log Koneksi TCP
|
||||
CMD_Log_1 Log Paket TCP
|
||||
CMD_Log_2 Log DHCP
|
||||
CMD_Log_3 Log UDP
|
||||
CMD_Log_4 Log ICMP
|
||||
CMD_Log_5 Log IP
|
||||
CMD_Log_6 Log ARP
|
||||
CMD_Log_7 Log Ethernet
|
||||
|
||||
|
||||
# LogEnable command
|
||||
CMD_LogEnable Mengaktifkan Log Keamanan atau Log Paket
|
||||
CMD_LogEnable_Help Gunakan ini untuk mengaktifkan log keamanan atau log paket dari Hub Virtual yang sedang dikelola. \nUntuk mendapatkan pengaturan saat ini, Anda dapat menggunakan perintah LogGet.
|
||||
CMD_LogEnable Mengaktifkan Log Keamanan atau Log Paket
|
||||
CMD_LogEnable_Help Gunakan ini untuk mengaktifkan log keamanan atau log paket dari Hub Virtual yang sedang dikelola. \nUntuk mendapatkan pengaturan saat ini, Anda dapat menggunakan perintah LogGet.
|
||||
CMD_LogEnable_Args LogEnable [security|packet]
|
||||
CMD_LogEnable_[security|packet] Pilih jenis log untuk diaktifkan. Tentukan "keamanan" atau "paket".
|
||||
CMD_LogEnable_Prompt Pilih Keamanan atau Paket:
|
||||
@ -5421,7 +5421,7 @@ CMD_CascadeEncryptDisable_[name] Tentukan nama Koneksi Cascade yang pengaturanny
|
||||
|
||||
# CascadeCompressEnable command
|
||||
CMD_CascadeCompressEnable Aktifkan Kompresi Data saat Berkomunikasi melalui Koneksi Cascade
|
||||
CMD_CascadeCompressEnable_Help Ketika Koneksi Cascade yang terdaftar pada Virtual Hub yang saat ini dikelola ditentukan dan Koneksi Cascade tersebut digunakan untuk komunikasi antara Server VPN melalui koneksi VPN, gunakan ini untuk mengatur agar isi komunikasi antara Server VPN dikompresi. \nMungkin mencapai kompresi maksimal hingga 80%. Namun, kompresi memberikan beban yang lebih tinggi pada CPU baik pada mesin klien maupun server. Ketika kecepatan garis sekitar 10 Mbps atau lebih, kompresi dapat menurunkan throughput, tetapi terkadang dapat memiliki efek sebaliknya. \nAnda tidak dapat menjalankan perintah ini untuk Virtual Hub pada Server VPN yang beroperasi sebagai cluster.
|
||||
CMD_CascadeCompressEnable_Help Ketika Koneksi Cascade yang terdaftar pada Virtual Hub yang saat ini dikelola ditentukan dan Koneksi Cascade tersebut digunakan untuk komunikasi antara Server VPN melalui koneksi VPN, gunakan ini untuk mengatur agar isi komunikasi antara Server VPN dikompresi. \nKompresi dapat mencapai hingga 80% efisiensi dalam mengurangi ukuran data. Namun, kompresi memberikan beban yang lebih tinggi pada CPU baik pada mesin klien maupun server. Ketika kecepatan garis sekitar 10 Mbps atau lebih, kompresi dapat menurunkan throughput, tetapi terkadang dapat memiliki efek sebaliknya. \nAnda tidak dapat menjalankan perintah ini untuk Virtual Hub pada Server VPN yang beroperasi sebagai cluster.
|
||||
CMD_CascadeCompressEnable_Args CascadeCompressEnable [name]
|
||||
CMD_CascadeCompressEnable_[name] Tentukan nama Koneksi Cascade yang pengaturannya ingin Anda ubah.
|
||||
|
||||
@ -5685,8 +5685,8 @@ CMD_AccessAddEx_SRCMAC Tentukan alamat MAC sumber sebagai aturan. Tentukan alam
|
||||
CMD_AccessAddEx_DESTMAC Tentukan alamat MAC tujuan sebagai aturan. Gunakan metode yang sama seperti untuk parameter /SRCMAC.
|
||||
CMD_AccessAddEx_TCPSTATE Tentukan status koneksi TCP sebagai aturan. Gunakan Established atau Unestablished.
|
||||
CMD_AccessAddEx_DELAY Tentukan nilai ini untuk menghasilkan keterlambatan ketika paket melewati. Tentukan periode keterlambatan dalam milidetik. Menentukan 0 berarti tidak ada keterlambatan yang dihasilkan. Keterlambatan maksimal adalah 10000 milidetik.
|
||||
CMD_AccessAddEx_JITTER Tentukan nilai ini untuk menghasilkan jitter ketika paket melewati. Tentukan rasio fluktuasi jitter dalam kisaran 0% hingga 100%. Menentukan 0 berarti tidak ada jitter yang dihasilkan.
|
||||
CMD_AccessAddEx_LOSS Tentukan nilai ini untuk menghasilkan kehilangan paket ketika paket melewati. Tentukan rasio kehilangan paket dalam kisaran 0% hingga 100%. Menentukan 0 berarti tidak ada kehilangan paket yang dihasilkan.
|
||||
CMD_AccessAddEx_JITTER Tentukan nilai ini untuk menghasilkan jitter ketika paket melewati. Rasio fluktuasi jitter dapat ditentukan dalam kisaran dari 0% hingga 100% sesuai kebutuhan. Menentukan 0 berarti tidak ada jitter yang dihasilkan.
|
||||
CMD_AccessAddEx_LOSS Tentukan nilai ini untuk menghasilkan kehilangan paket ketika paket melewati. Rasio kehilangan paket dapat ditentukan dalam kisaran dari 0% hingga 100% sesuai kebutuhan. Menentukan 0 berarti tidak ada kehilangan paket yang dihasilkan.
|
||||
CMD_AccessAddEx_REDIRECTURL URL yang ditentukan akan dijawab wajib kepada klien sebagai respons untuk paket permintaan koneksi TCP yang cocok dengan kondisi entri daftar akses ini melalui Virtual Hub ini. Untuk menggunakan pengaturan ini, kamu dapat memaksa browser web di komputer VPN Client untuk menunjukkan situs web yang ditentukan ketika browser tersebut mencoba mengakses alamat IP tertentu.
|
||||
CMD_AccessAddEx_Prompt_DELAY Keterlambatan yang Akan Dihasilkan (dalam milidetik: 0 - 10000):
|
||||
CMD_AccessAddEx_Prompt_JITTER Fluktuasi Jitter yang Akan Dihasilkan (Persen: 0 - 100):
|
||||
@ -5747,8 +5747,8 @@ CMD_AccessAddEx6_SRCMAC Tentukan alamat MAC sumber sebagai aturan. Tentukan ala
|
||||
CMD_AccessAddEx6_DESTMAC Tentukan alamat MAC tujuan sebagai aturan. Gunakan metode yang sama seperti untuk parameter /SRCMAC.
|
||||
CMD_AccessAddEx6_TCPSTATE Tentukan status koneksi TCP sebagai aturan. Gunakan Established atau Unestablished.
|
||||
CMD_AccessAddEx6_DELAY Tentukan nilai ini untuk menghasilkan keterlambatan saat paket melewati. Tentukan periode keterlambatan dalam milidetik. Tentukan 0 berarti tidak ada keterlambatan yang dihasilkan. Keterlambatan maksimal yang dapat dihasilkan adalah 10000 milidetik.
|
||||
CMD_AccessAddEx6_JITTER Tentukan nilai ini untuk menghasilkan jitter saat paket melewati. Tentukan rasio fluktuasi jitter dalam rentang 0% hingga 100%. Tentukan 0 berarti tidak ada jitter yang dihasilkan.
|
||||
CMD_AccessAddEx6_LOSS Tentukan nilai ini untuk menghasilkan kehilangan paket saat paket melewati. Tentukan rasio kehilangan paket dalam rentang 0% hingga 100%. Tentukan 0 berarti tidak ada kehilangan paket yang dihasilkan.
|
||||
CMD_AccessAddEx6_JITTER Tentukan nilai ini untuk menghasilkan jitter ketika paket melewati. Rasio fluktuasi jitter dapat ditentukan dalam kisaran dari 0% hingga 100% sesuai kebutuhan. Menentukan 0 berarti tidak ada jitter yang dihasilkan.
|
||||
CMD_AccessAddEx6_LOSS Tentukan nilai ini untuk menghasilkan kehilangan paket ketika paket melewati. Rasio kehilangan paket dapat ditentukan dalam kisaran dari 0% hingga 100% sesuai kebutuhan. Menentukan 0 berarti tidak ada kehilangan paket yang dihasilkan.
|
||||
CMD_AccessAddEx6_REDIRECTURL URL yang ditentukan akan dijawab secara wajib kepada klien sebagai respons untuk paket permintaan koneksi TCP yang cocok dengan kondisi entri daftar akses ini melalui Virtual Hub ini. Untuk menggunakan pengaturan ini, kamu dapat memaksa peramban web pada komputer VPN Client untuk menampilkan situs web yang ditentukan ketika peramban web tersebut mencoba mengakses alamat IP tertentu.
|
||||
CMD_AccessAddEx6_Prompt_DELAY Keterlambatan untuk Dihasilkan (dalam milidetik: 0 - 10000):
|
||||
CMD_AccessAddEx6_Prompt_JITTER Fluktuasi Jitter untuk Dihasilkan (Persen: 0 - 100):
|
||||
@ -6728,7 +6728,7 @@ CMD_AccountEncryptDisable_[name] Tentukan nama Pengaturan Koneksi VPN yang penga
|
||||
|
||||
# AccountCompressEnable command
|
||||
CMD_AccountCompressEnable Aktifkan Kompresi Data saat Berkomunikasi melalui Pengaturan Koneksi VPN
|
||||
CMD_AccountCompressEnable_Help Ketika Pengaturan Koneksi VPN yang terdaftar di VPN Client ditentukan dan Pengaturan Koneksi VPN tersebut digunakan untuk komunikasi antara VPN Server melalui koneksi VPN, gunakan ini untuk mengatur konten komunikasi antara VPN Server agar dikompresi. \nKompresi dapat mencapai hingga 80%. Namun, kompresi memberikan beban yang lebih tinggi pada CPU baik di mesin klien maupun server. Ketika kecepatan jalur sekitar 10 Mbps atau lebih, kompresi dapat menurunkan throughput, tetapi kadang-kadang dapat memiliki efek sebaliknya.
|
||||
CMD_AccountCompressEnable_Help Ketika Pengaturan Koneksi VPN yang terdaftar di VPN Client ditentukan dan Pengaturan Koneksi VPN tersebut digunakan untuk komunikasi antara VPN Server melalui koneksi VPN, gunakan ini untuk mengatur konten komunikasi antara VPN Server agar dikompresi. \nKompresi dapat mencapai hingga 80% efisiensi dalam mengurangi ukuran data. Namun, kompresi memberikan beban yang lebih tinggi pada CPU baik di mesin klien maupun server. Ketika kecepatan jalur sekitar 10 Mbps atau lebih, kompresi dapat menurunkan throughput, tetapi kadang-kadang dapat memiliki efek sebaliknya.
|
||||
CMD_AccountCompressEnable_Args AccountCompressEnable [name]
|
||||
CMD_AccountCompressEnable_[name] Tentukan nama Pengaturan Koneksi VPN yang pengaturannya ingin Anda ubah.
|
||||
|
||||
|
Reference in New Issue
Block a user