diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index 34a62b1ff..51061795f 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -9,6 +9,7 @@ As a contributor, here are the guidelines we would like you to follow:
* [Git Workflow](#git)
* [Commit Message Guidelines](#commit)
* [Coding Conventions](#conventions)
+* [Beta Program](#beta-program)
## Contributing Code
@@ -108,4 +109,18 @@ This projects is using [SwiftLint](https://github.com/realm/SwiftLint) to enforc
```sh
$ fastlane lint
-```
\ No newline at end of file
+```
+
+
+## IVPN iOS App Beta Program
+
+Users with an active IVPN account can join our iOS app beta program:
+
+1. Install the iOS [TestFlight app](https://testflight.apple.com)
+2. Open [https://testflight.apple.com/join/FnmEzHHb](https://testflight.apple.com/join/FnmEzHHb) on your iOS device
+3. You will be presented with detailed instructions on how to install the IVPN iOS beta app
+
+Any feedback will be very useful to us. You can submit feedback either by opening an issue on [GitHub](https://github.com/ivpn/ios-app/issues), or send a direct message to beta@ivpn.net.
+
+**IMPORTANT NOTE:**
+Do not use IVPN prerelease (beta) apps in situations where you need to protect your privacy or security, but only for testing new unreleased features and improvements.
diff --git a/.github/SECURITY.md b/.github/SECURITY.md
index efd4d673a..a0ddf6345 100644
--- a/.github/SECURITY.md
+++ b/.github/SECURITY.md
@@ -2,7 +2,7 @@
## Reporting a security vulnerability to IVPN
-If you believe you have found a security vulnerability, **DO NOT CREATE AN ISSUE**. Instead, please send an email to security@ivpn.net. We treat all reports with the highest priority and confidentiality.
+If you believe you have found a security vulnerability, **DO NOT CREATE AN ISSUE**. Instead, please send an email to security@ivpn.net or file a report directly on GitHub with [Private vulnerability reporting](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing/privately-reporting-a-security-vulnerability). We treat all reports with the highest priority and confidentiality.
## Incident resolution process
@@ -58,4 +58,4 @@ fw0vw5vWVvCDLCQx+sLeNNwWl8291JZNPaSjhuUkK7npNRHV8M3AC5UhhJjwS5K98YeZUeE/4SLN
T7Vor9NUBZb2g6gu2CwiPAhOS5TY/Oqgh3rvBcDS8X9pgOYXpnTrRLJNhZEjNawRvsqbjJV7vpzL
x6/Qj0RvfminJWZZz54gHHuh/98PpmByzXLdpQ8GH+PiUd8n5AyA9FxW81kSLTE==o/fv
-----END PGP PUBLIC KEY BLOCK-----
-```
\ No newline at end of file
+```
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 98fc17587..6ccf33779 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,14 @@
All notable changes to this project will be documented in this file.
+## 2.7.0 - 2022-11-23
+
+[NEW] Ability to connect to a specific host in a location
+[NEW] Support for custom ports
+[IMPROVED] Warning about existing VPN connection(s) when downgrading subscription plan
+[FIXED] IPv6 connection information not displayed on iOS 16+ devices
+[FIXED] Port number displayed in the settings when MultiHop is enabled
+
## 2.6.3 - 2022-05-17
[IMPROVED] Option to select UDP or TCP when using OpenVPN MultiHop
diff --git a/Gemfile.lock b/Gemfile.lock
index 25eb019d7..a9ed3cfb8 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -187,7 +187,7 @@ GEM
tty-screen (0.7.0)
tty-spinner (0.9.2)
tty-cursor (~> 0.7)
- tzinfo (1.2.6)
+ tzinfo (1.2.10)
thread_safe (~> 0.1)
uber (0.1.0)
unf (0.1.4)
diff --git a/IVPNClient.xcodeproj/project.pbxproj b/IVPNClient.xcodeproj/project.pbxproj
index fa2e33aa8..0e215d88f 100644
--- a/IVPNClient.xcodeproj/project.pbxproj
+++ b/IVPNClient.xcodeproj/project.pbxproj
@@ -39,6 +39,9 @@
821429BB22FC36100056B8FF /* ApiRequestDI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 821429BA22FC36100056B8FF /* ApiRequestDI.swift */; };
821AFA1323602B71001EF617 /* SettingsScreenTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 821AFA1223602B71001EF617 /* SettingsScreenTests.swift */; };
821BDE02224A6EC700F592BF /* AppKeyManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 821BDE01224A6EC700F592BF /* AppKeyManagerTests.swift */; };
+ 821CA2D7287C5AB20067F70D /* PortViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 821CA2D6287C5AB20067F70D /* PortViewController.swift */; };
+ 821CA2DB288039670067F70D /* PortTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 821CA2DA288039670067F70D /* PortTableViewCell.swift */; };
+ 821CA2DF288143470067F70D /* PortRange.swift in Sources */ = {isa = PBXBuildFile; fileRef = 821CA2DE288143470067F70D /* PortRange.swift */; };
821F1C7E21FF544200107311 /* VPNServerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 821F1C7D21FF544200107311 /* VPNServerViewModel.swift */; };
821F604A240D21E3008072D7 /* ControlPanelViewController+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 821F6049240D21E3008072D7 /* ControlPanelViewController+Ext.swift */; };
8221377B2227E75E001E1BF5 /* CustomDNSViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8221377A2227E75E001E1BF5 /* CustomDNSViewController.swift */; };
@@ -205,6 +208,9 @@
82AA85782514DEB40027DAB8 /* Date+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82D90470216C7DAF0032F3BE /* Date+Ext.swift */; };
82AA8818231E330A00E18ECB /* SessionStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82AA8817231E330A00E18ECB /* SessionStatus.swift */; };
82AAF0E92253A4A8005E792F /* StaticWebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82AAF0E82253A4A8005E792F /* StaticWebViewController.swift */; };
+ 82AB0875291A6B5F0084625A /* AddCustomPortViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82AB0874291A6B5F0084625A /* AddCustomPortViewController.swift */; };
+ 82AB0877291A6B9C0084625A /* CustomPort+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82AB0876291A6B9C0084625A /* CustomPort+CoreDataClass.swift */; };
+ 82AB0879291A6BB90084625A /* CustomPort+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82AB0878291A6BB90084625A /* CustomPort+CoreDataProperties.swift */; };
82B51CDF21DE3E31005CC9C9 /* UITableView+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82B51CDE21DE3E31005CC9C9 /* UITableView+Ext.swift */; };
82B605262170840C004B40E6 /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82B605252170840C004B40E6 /* PacketTunnelProvider.swift */; };
82B6052B2170840C004B40E6 /* wireguard-tunnel-provider.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 82B605232170840C004B40E6 /* wireguard-tunnel-provider.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
@@ -436,6 +442,9 @@
821429BA22FC36100056B8FF /* ApiRequestDI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApiRequestDI.swift; sourceTree = ""; };
821AFA1223602B71001EF617 /* SettingsScreenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScreenTests.swift; sourceTree = ""; };
821BDE01224A6EC700F592BF /* AppKeyManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppKeyManagerTests.swift; sourceTree = ""; };
+ 821CA2D6287C5AB20067F70D /* PortViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PortViewController.swift; sourceTree = ""; };
+ 821CA2DA288039670067F70D /* PortTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PortTableViewCell.swift; sourceTree = ""; };
+ 821CA2DE288143470067F70D /* PortRange.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PortRange.swift; sourceTree = ""; };
821F1C7D21FF544200107311 /* VPNServerViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNServerViewModel.swift; sourceTree = ""; };
821F6049240D21E3008072D7 /* ControlPanelViewController+Ext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ControlPanelViewController+Ext.swift"; sourceTree = ""; };
8221377A2227E75E001E1BF5 /* CustomDNSViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomDNSViewController.swift; sourceTree = ""; };
@@ -557,6 +566,9 @@
82A9E8C823471FB2007BCA7E /* wg-staging.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "wg-staging.xcconfig"; sourceTree = ""; };
82AA8817231E330A00E18ECB /* SessionStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionStatus.swift; sourceTree = ""; };
82AAF0E82253A4A8005E792F /* StaticWebViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticWebViewController.swift; sourceTree = ""; };
+ 82AB0874291A6B5F0084625A /* AddCustomPortViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddCustomPortViewController.swift; sourceTree = ""; };
+ 82AB0876291A6B9C0084625A /* CustomPort+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CustomPort+CoreDataClass.swift"; sourceTree = ""; };
+ 82AB0878291A6BB90084625A /* CustomPort+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CustomPort+CoreDataProperties.swift"; sourceTree = ""; };
82B51CDE21DE3E31005CC9C9 /* UITableView+Ext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITableView+Ext.swift"; sourceTree = ""; };
82B605232170840C004B40E6 /* wireguard-tunnel-provider.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "wireguard-tunnel-provider.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
82B605252170840C004B40E6 /* PacketTunnelProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PacketTunnelProvider.swift; sourceTree = ""; };
@@ -928,6 +940,7 @@
82DAB37A2457013900302F4C /* Service.swift */,
8243587025DBB73E005FDEBB /* SecureDNS.swift */,
827694F2263C04C40058B4DC /* LoginConfirmation.swift */,
+ 821CA2DE288143470067F70D /* PortRange.swift */,
);
path = Models;
sourceTree = "";
@@ -1187,6 +1200,8 @@
8269CAC22264962F00CF488A /* AntiTrackerViewController.swift */,
82F917382344861A0025ED3A /* TermsOfServiceViewController.swift */,
8201A5032356536B008C83DB /* UpgradePlanViewController.swift */,
+ 821CA2D6287C5AB20067F70D /* PortViewController.swift */,
+ 82AB0874291A6B5F0084625A /* AddCustomPortViewController.swift */,
);
path = ViewControllers;
sourceTree = "";
@@ -1202,6 +1217,7 @@
82824829225C7312001314F8 /* WireGuardRegenerationRateCell.swift */,
82DAB37E2457260000302F4C /* ServiceTableViewCell.swift */,
82DAB37C245725E200302F4C /* ServiceTitleTableViewCell.swift */,
+ 821CA2DA288039670067F70D /* PortTableViewCell.swift */,
);
path = TableCells;
sourceTree = "";
@@ -1222,6 +1238,8 @@
824777E621A6BC3A001EEFAF /* Network+CoreDataProperties.swift */,
82A160B8221C4E2000730577 /* Server+CoreDataClass.swift */,
82A160B9221C4E2000730577 /* Server+CoreDataProperties.swift */,
+ 82AB0876291A6B9C0084625A /* CustomPort+CoreDataClass.swift */,
+ 82AB0878291A6BB90084625A /* CustomPort+CoreDataProperties.swift */,
);
path = CoreData;
sourceTree = "";
@@ -2152,6 +2170,7 @@
828772F9221C01C300D5E330 /* ServersConfigurationTableViewController.swift in Sources */,
82989FDE2188981900F7EBE0 /* AppKeyManager.swift in Sources */,
8243584E25DAA842005FDEBB /* SecureDNSView.swift in Sources */,
+ 821CA2DB288039670067F70D /* PortTableViewCell.swift in Sources */,
8206F32124347A8F0056B465 /* MainView.swift in Sources */,
9C50959A20FCF6850048DBF2 /* ProtocolTableViewCell.swift in Sources */,
828D8A6D258245AD00CB0E5B /* TwoFactorViewController.swift in Sources */,
@@ -2192,6 +2211,7 @@
8208525C23FD64160008C112 /* MainViewController+Ext.swift in Sources */,
82C1D5BF23FE8C6D0059A915 /* ControlPanelViewController.swift in Sources */,
82DEFFA62452DE5100ECB482 /* MapConstants.swift in Sources */,
+ 82AB0875291A6B5F0084625A /* AddCustomPortViewController.swift in Sources */,
8277F1CD22118D08007C6F15 /* ProofsViewModel.swift in Sources */,
8269CAC32264962F00CF488A /* AntiTrackerViewController.swift in Sources */,
82E5449224EE584E006DEF8D /* UIImageView+Ext.swift in Sources */,
@@ -2251,6 +2271,7 @@
9CB2CE411DB2594A007A4D2D /* VPNServerList.swift in Sources */,
823FFB072338DF1800F91A5D /* Capability.swift in Sources */,
82061F65238D2730009DDF4D /* Ping.swift in Sources */,
+ 82AB0879291A6BB90084625A /* CustomPort+CoreDataProperties.swift in Sources */,
82AAF0E92253A4A8005E792F /* StaticWebViewController.swift in Sources */,
8282482A225C7312001314F8 /* WireGuardRegenerationRateCell.swift in Sources */,
824777EA21A6BC3A001EEFAF /* Network+CoreDataProperties.swift in Sources */,
@@ -2295,10 +2316,13 @@
820079F42407D96D00EC2062 /* ConnectionInfoBoxView.swift in Sources */,
9C69422E1DD20FC200F9A801 /* KeyChain.swift in Sources */,
821429BB22FC36100056B8FF /* ApiRequestDI.swift in Sources */,
+ 82AB0877291A6B9C0084625A /* CustomPort+CoreDataClass.swift in Sources */,
82C1D5BC23FE78570059A915 /* MapScrollView.swift in Sources */,
82AA8818231E330A00E18ECB /* SessionStatus.swift in Sources */,
9C28337E1D9D3F060024C553 /* Config.swift in Sources */,
82DAB37F2457260000302F4C /* ServiceTableViewCell.swift in Sources */,
+ 821CA2DF288143470067F70D /* PortRange.swift in Sources */,
+ 821CA2D7287C5AB20067F70D /* PortViewController.swift in Sources */,
82061F66238D2730009DDF4D /* ICMPHeader.swift in Sources */,
826F7F0C23A79F1500777DB9 /* UserDefaultsTodayExtension+Ext.swift in Sources */,
824BC466240906ED00A61B29 /* VPNStatusViewModel.swift in Sources */,
@@ -2513,7 +2537,7 @@
CODE_SIGN_ENTITLEMENTS = "today-extension/today-extension.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 6;
+ CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = WQXXM75BYN;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = "today-extension/Info.plist";
@@ -2523,7 +2547,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
- MARKETING_VERSION = 2.6.2;
+ MARKETING_VERSION = 2.7.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "net.ivpn.clients.ios.today-extension";
@@ -2546,7 +2570,7 @@
CODE_SIGN_ENTITLEMENTS = "today-extension/today-extension.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 6;
+ CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = WQXXM75BYN;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = "today-extension/Info.plist";
@@ -2556,7 +2580,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
- MARKETING_VERSION = 2.6.2;
+ MARKETING_VERSION = 2.7.0;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "net.ivpn.clients.ios.today-extension";
PRODUCT_NAME = IVPN;
@@ -2578,7 +2602,7 @@
CODE_SIGN_ENTITLEMENTS = "today-extension/today-extension.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 6;
+ CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = WQXXM75BYN;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = "today-extension/Info.plist";
@@ -2588,7 +2612,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
- MARKETING_VERSION = 2.6.2;
+ MARKETING_VERSION = 2.7.0;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "net.ivpn.clients.ios.today-extension";
PRODUCT_NAME = IVPN;
@@ -2610,7 +2634,7 @@
CODE_SIGN_ENTITLEMENTS = "wireguard-tunnel-provider/wireguard_tunnel_provider.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 6;
+ CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = WQXXM75BYN;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -2626,7 +2650,7 @@
"@executable_path/../../Frameworks",
);
LIBRARY_SEARCH_PATHS = "$(inherited)";
- MARKETING_VERSION = 2.6.2;
+ MARKETING_VERSION = 2.7.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "net.ivpn.clients.ios.wireguard-tunnel-provider";
@@ -2649,7 +2673,7 @@
CODE_SIGN_ENTITLEMENTS = "wireguard-tunnel-provider/wireguard_tunnel_provider.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 6;
+ CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = WQXXM75BYN;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -2665,7 +2689,7 @@
"@executable_path/../../Frameworks",
);
LIBRARY_SEARCH_PATHS = "$(inherited)";
- MARKETING_VERSION = 2.6.2;
+ MARKETING_VERSION = 2.7.0;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "net.ivpn.clients.ios.wireguard-tunnel-provider";
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -2828,7 +2852,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = IVPNClient/IVPNClient.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
- CURRENT_PROJECT_VERSION = 6;
+ CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = WQXXM75BYN;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -2841,7 +2865,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
- MARKETING_VERSION = 2.6.2;
+ MARKETING_VERSION = 2.7.0;
OTHER_LDFLAGS = (
"$(inherited)",
"-framework",
@@ -2909,7 +2933,7 @@
CODE_SIGN_ENTITLEMENTS = "openvpn-tunnel-provider/openvpn_tunnel_provider.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 6;
+ CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = WQXXM75BYN;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -2923,7 +2947,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
- MARKETING_VERSION = 2.6.2;
+ MARKETING_VERSION = 2.7.0;
OTHER_SWIFT_FLAGS = "-D DEBUG";
PRODUCT_BUNDLE_IDENTIFIER = "net.ivpn.clients.ios.openvpn-tunnel-provider";
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -2944,7 +2968,7 @@
CODE_SIGN_ENTITLEMENTS = "wireguard-tunnel-provider/wireguard_tunnel_provider.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 6;
+ CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = WQXXM75BYN;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -2960,7 +2984,7 @@
"@executable_path/../../Frameworks",
);
LIBRARY_SEARCH_PATHS = "$(inherited)";
- MARKETING_VERSION = 2.6.2;
+ MARKETING_VERSION = 2.7.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "net.ivpn.clients.ios.wireguard-tunnel-provider";
@@ -2993,7 +3017,7 @@
CODE_SIGN_ENTITLEMENTS = "openvpn-tunnel-provider/openvpn_tunnel_provider.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 6;
+ CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = WQXXM75BYN;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -3007,7 +3031,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
- MARKETING_VERSION = 2.6.2;
+ MARKETING_VERSION = 2.7.0;
OTHER_SWIFT_FLAGS = "-D DEBUG";
PRODUCT_BUNDLE_IDENTIFIER = "net.ivpn.clients.ios.openvpn-tunnel-provider";
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -3038,7 +3062,7 @@
CODE_SIGN_ENTITLEMENTS = "openvpn-tunnel-provider/openvpn_tunnel_provider.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 6;
+ CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = WQXXM75BYN;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -3052,7 +3076,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
- MARKETING_VERSION = 2.6.2;
+ MARKETING_VERSION = 2.7.0;
OTHER_SWIFT_FLAGS = "-D RELEASE";
PRODUCT_BUNDLE_IDENTIFIER = "net.ivpn.clients.ios.openvpn-tunnel-provider";
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -3191,7 +3215,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = IVPNClient/IVPNClient.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
- CURRENT_PROJECT_VERSION = 6;
+ CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = WQXXM75BYN;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -3204,7 +3228,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
- MARKETING_VERSION = 2.6.2;
+ MARKETING_VERSION = 2.7.0;
OTHER_LDFLAGS = (
"$(inherited)",
"-framework",
@@ -3230,7 +3254,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = IVPNClient/IVPNClient.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
- CURRENT_PROJECT_VERSION = 6;
+ CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = WQXXM75BYN;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -3244,7 +3268,7 @@
"@executable_path/Frameworks",
"$(SRCROOT)/Carthage/Build/iOS",
);
- MARKETING_VERSION = 2.6.2;
+ MARKETING_VERSION = 2.7.0;
OTHER_LDFLAGS = (
"$(inherited)",
"-framework",
diff --git a/IVPNClient/AppDelegate.swift b/IVPNClient/AppDelegate.swift
index d7d815519..c5c033a51 100644
--- a/IVPNClient/AppDelegate.swift
+++ b/IVPNClient/AppDelegate.swift
@@ -167,11 +167,7 @@ class AppDelegate: UIResponder {
})
case Config.urlTypeLogin:
if let topViewController = UIApplication.topViewController() {
- if #available(iOS 13.0, *) {
- topViewController.present(NavigationManager.getLoginViewController(), animated: true, completion: nil)
- } else {
- topViewController.present(NavigationManager.getLoginViewController(), animated: true, completion: nil)
- }
+ topViewController.present(NavigationManager.getLoginViewController(), animated: true, completion: nil)
}
default:
break
diff --git a/IVPNClient/Assets.xcassets/icon-arrow-down-gray.imageset/Contents.json b/IVPNClient/Assets.xcassets/icon-arrow-down-gray.imageset/Contents.json
new file mode 100644
index 000000000..899f6954c
--- /dev/null
+++ b/IVPNClient/Assets.xcassets/icon-arrow-down-gray.imageset/Contents.json
@@ -0,0 +1,15 @@
+{
+ "images" : [
+ {
+ "filename" : "icon-arrow-down-gray.pdf",
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ },
+ "properties" : {
+ "template-rendering-intent" : "template"
+ }
+}
diff --git a/IVPNClient/Assets.xcassets/icon-arrow-down-gray.imageset/icon-arrow-down-gray.pdf b/IVPNClient/Assets.xcassets/icon-arrow-down-gray.imageset/icon-arrow-down-gray.pdf
new file mode 100644
index 000000000..240e8fdfc
Binary files /dev/null and b/IVPNClient/Assets.xcassets/icon-arrow-down-gray.imageset/icon-arrow-down-gray.pdf differ
diff --git a/IVPNClient/Assets.xcassets/icon-arrow-left-gray.imageset/icon-arrow-left.pdf b/IVPNClient/Assets.xcassets/icon-arrow-left-gray.imageset/icon-arrow-left.pdf
index ff60a0e57..f424e1d45 100644
Binary files a/IVPNClient/Assets.xcassets/icon-arrow-left-gray.imageset/icon-arrow-left.pdf and b/IVPNClient/Assets.xcassets/icon-arrow-left-gray.imageset/icon-arrow-left.pdf differ
diff --git a/IVPNClient/Assets.xcassets/icon-arrow-up-gray.imageset/Contents.json b/IVPNClient/Assets.xcassets/icon-arrow-up-gray.imageset/Contents.json
new file mode 100644
index 000000000..4685ba0eb
--- /dev/null
+++ b/IVPNClient/Assets.xcassets/icon-arrow-up-gray.imageset/Contents.json
@@ -0,0 +1,15 @@
+{
+ "images" : [
+ {
+ "filename" : "icon-arrow-up-gray.pdf",
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ },
+ "properties" : {
+ "template-rendering-intent" : "template"
+ }
+}
diff --git a/IVPNClient/Assets.xcassets/icon-arrow-up-gray.imageset/icon-arrow-up-gray.pdf b/IVPNClient/Assets.xcassets/icon-arrow-up-gray.imageset/icon-arrow-up-gray.pdf
new file mode 100644
index 000000000..f3ab1e5c1
Binary files /dev/null and b/IVPNClient/Assets.xcassets/icon-arrow-up-gray.imageset/icon-arrow-up-gray.pdf differ
diff --git a/IVPNClient/Config/Config.swift b/IVPNClient/Config/Config.swift
index a3fd10fbd..3548fd594 100644
--- a/IVPNClient/Config/Config.swift
+++ b/IVPNClient/Config/Config.swift
@@ -65,29 +65,6 @@ struct Config {
static let stableVPNStatusInterval: TimeInterval = 0.5
static let defaultProtocol = ConnectionSettings.wireguard(.udp, 2049)
- static let supportedProtocols = [
- ConnectionSettings.ipsec,
- ConnectionSettings.openvpn(.udp, 2049),
- ConnectionSettings.openvpn(.udp, 2050),
- ConnectionSettings.openvpn(.udp, 53),
- // ConnectionSettings.openvpn(.udp, 80),
- // ConnectionSettings.openvpn(.udp, 443),
- ConnectionSettings.openvpn(.udp, 1194),
- ConnectionSettings.openvpn(.tcp, 443),
- ConnectionSettings.openvpn(.tcp, 1443),
- ConnectionSettings.openvpn(.tcp, 80),
- ConnectionSettings.wireguard(.udp, 2049),
- ConnectionSettings.wireguard(.udp, 2050),
- ConnectionSettings.wireguard(.udp, 53),
- // ConnectionSettings.wireguard(.udp, 80),
- // ConnectionSettings.wireguard(.udp, 443),
- ConnectionSettings.wireguard(.udp, 1194),
- ConnectionSettings.wireguard(.udp, 30587),
- ConnectionSettings.wireguard(.udp, 41893),
- ConnectionSettings.wireguard(.udp, 48574),
- ConnectionSettings.wireguard(.udp, 58237)
- ]
-
static let supportedProtocolTypes = [
ConnectionSettings.wireguard(.udp, 2049),
ConnectionSettings.ipsec,
diff --git a/IVPNClient/Config/servers.json b/IVPNClient/Config/servers.json
index 8607b6c0f..b8b32a9d8 100644
--- a/IVPNClient/Config/servers.json
+++ b/IVPNClient/Config/servers.json
@@ -1 +1 @@
-{"wireguard":[{"gateway":"us-tx.wg.ivpn.net","country_code":"US","country":"United States","city":"Dallas, TX","latitude":32.7936,"longitude":-96.7662,"isp":"Quadranet","hosts":[{"hostname":"us-tx1.wg.ivpn.net","host":"198.55.124.114","public_key":"JPT1veXLmasj2uQDstX24mpR7VWD+GmV8JDkidkz91Q=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":21010},{"hostname":"us-tx01.wg.ivpn.net","host":"96.44.189.197","public_key":"LvWf548mFddi8PTrIGL6uD1/l85LU8z0Rc8tpvw2Vls=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":21001},{"hostname":"us-tx2.wg.ivpn.net","host":"96.44.142.77","public_key":"om8hOGUcEvoOhHvJZoBHxNF4jxY/+Ml9Iy1WOSC/pFo=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":25001}]},{"gateway":"nl.wg.ivpn.net","country_code":"NL","country":"Netherlands","city":"Amsterdam","latitude":52.35,"longitude":4.9166,"isp":"Datapacket","hosts":[{"hostname":"nl1.wg.ivpn.net","host":"185.102.218.104","public_key":"AsMT2FqpkZbjzWeDch6GwufF5odl259W/hIkGytVfWo=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":20301},{"hostname":"nl4.wg.ivpn.net","host":"95.211.95.19","public_key":"cVB66gPq5cZ9dfXY+e2pbsCyih5o1zk04l5c5VCsV1g=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":23201},{"hostname":"nl3.wg.ivpn.net","host":"95.211.95.9","public_key":"XDU6Syq1DY82IMatsHV0x/TAtbLiRwh/SdFCXlEn40c=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":23101},{"hostname":"nl6.wg.ivpn.net","host":"95.211.243.182","public_key":"hMWpqb3FEATHIbImPVWB/5z2nWIXghwpnJjevPY+1H0=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":24101},{"hostname":"nl5.wg.ivpn.net","host":"95.211.243.162","public_key":"NCagAawwRixI6Iw/NWiGD8lbjDNCl0aTICZKJtO/1HA=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":23901},{"hostname":"nl7.wg.ivpn.net","host":"95.211.172.105","public_key":"hQNYqtfOOAEz0IGshLx/TI9hUrfR9gIIkjVm4VsCbBM=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":22501},{"hostname":"nl8.wg.ivpn.net","host":"95.211.198.167","public_key":"/nY1/OhVhdHtbnU/s31zYUuPBH0pizv4DemW5KDOUkg=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":22801}]},{"gateway":"de.wg.ivpn.net","country_code":"DE","country":"Germany","city":"Frankfurt","latitude":50.1,"longitude":8.675,"isp":"Datapacket","hosts":[{"hostname":"de1.wg.ivpn.net","host":"185.102.219.26","public_key":"mS3/WpXjnMAMmXjSpd4nFzx9HSE3ubv2WyjpyH2REgs=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":23010},{"hostname":"de01.wg.ivpn.net","host":"178.162.212.24","public_key":"Sc5AUZieg0qX8kyCy9p0OHRES4n0CHtHHM+ZPyERFTc=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":23001},{"hostname":"de2.wg.ivpn.net","host":"37.58.60.151","public_key":"QhY3OtBf4FFafKtLO33e6k8JnAl8e6ktFcRUyLjCDVY=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":22001}]},{"gateway":"us-il.wg.ivpn.net","country_code":"US","country":"United States","city":"Chicago, IL","latitude":41.8373,"longitude":-87.6862,"isp":"Datapacket","hosts":[{"hostname":"us-il1.wg.ivpn.net","host":"89.187.181.116","public_key":"hku9gjamhoii8OvxZgx+TdUDIkOAQYFu39qbav2AyUQ=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":21410},{"hostname":"us-il01.wg.ivpn.net","host":"72.11.137.158","public_key":"Uy5a8JOqneAUY1dC5s9jubLnotbyIfBsLP2nZuzRbHs=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":21401},{"hostname":"us-il2.wg.ivpn.net","host":"72.11.137.148","public_key":"ANhVUMAQgStPVNRHW8mg0ZtN1YI1QHyXfNCO8+USNQQ=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":24901}]},{"gateway":"us-ga.wg.ivpn.net","country_code":"US","country":"United States","city":"Atlanta, GA","latitude":33.7627,"longitude":-84.4225,"isp":"Datapacket","hosts":[{"hostname":"us-ga1.wg.ivpn.net","host":"185.93.0.212","public_key":"jD8h+pL5/d6fmYcTzl0lR8AWzQVN5XkwRFSmM/3NcDM=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":24510},{"hostname":"us-ga01.wg.ivpn.net","host":"104.129.24.149","public_key":"EJFl28aYpZKfmJqb1jxxTEnGx6kaH2USVrigpHKKXhs=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":24501},{"hostname":"us-ga2.wg.ivpn.net","host":"107.150.22.77","public_key":"hr2uQOEGCvGeDkoCQJ2dCI8dM8Iu5aKhb1PIvJ9q72E=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":24810}]},{"gateway":"us-ca.wg.ivpn.net","country_code":"US","country":"United States","city":"Los Angeles, CA","latitude":34.1139,"longitude":-118.4068,"isp":"Datapacket","hosts":[{"hostname":"us-ca1.wg.ivpn.net","host":"185.180.13.41","public_key":"FGl78s9Ct6xNamQ2/CtAyXwGePrrU0kiZxfM27pm8XA=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":22210},{"hostname":"us-ca01.wg.ivpn.net","host":"216.144.236.44","public_key":"B+qXdkIuETpzI0bfhGUAHN4SU91Tjs6ItdFlu93S42I=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":22201},{"hostname":"us-ca2.wg.ivpn.net","host":"216.144.236.68","public_key":"qv4Tupfon5NUSwzDpM8zPizSwJZn2h+9CqrufcyDOko=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":22401},{"hostname":"us-ca3.wg.ivpn.net","host":"198.54.129.100","public_key":"J5+Bx84LxNPdWEhewOvBV/fGWiDluIBlAcr1QlJZil8=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":21301},{"hostname":"us-ca4.wg.ivpn.net","host":"216.144.237.83","public_key":"dYPXYr6HSRJPe3MhALwGWNtdEy1+EPE9Kqv7cTrUXk8=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":21901}]},{"gateway":"ca-qc.wg.ivpn.net","country_code":"CA","country":"Canada","city":"Montreal","latitude":45.5,"longitude":-73.5833,"isp":"M247","hosts":[{"hostname":"ca1.wg.ivpn.net","host":"37.120.130.58","public_key":"rg+GGDmjM4Vxo1hURvKmgm9yonb6qcoKbPCP/DNDBnI=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":23810},{"hostname":"ca-qc1.wg.ivpn.net","host":"87.101.92.29","public_key":"98JU1mdCR8vD1aNZg017/NjBeTjuuCKUaLw0zfz/CUE=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":27001}]},{"gateway":"gb.wg.ivpn.net","country_code":"GB","country":"United Kingdom","city":"London","latitude":51.5,"longitude":-0.1167,"isp":"M247","hosts":[{"hostname":"gb1.wg.ivpn.net","host":"81.92.202.114","public_key":"7+jos+Eg+hMEOQE4Std6OJ+WVnCcmbqS1/EbPwn9w3s=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":20810},{"hostname":"gb2.wg.ivpn.net","host":"185.59.221.225","public_key":"x0BTRaxsdxAd58ZyU2YMX4bmuj+Eg+8/urT2F3Vs1n8=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":24201},{"hostname":"gb01.wg.ivpn.net","host":"185.59.221.140","public_key":"yKK5x+D17Jr3Q12T/UBaDjNVmNdZBsqpvTqH6YfsGHg=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":20801}]},{"gateway":"us-ny.wg.ivpn.net","country_code":"US","country":"United States","city":"New York, NY","latitude":40.6943,"longitude":-73.9249,"isp":"M247","hosts":[{"hostname":"us-ny1.wg.ivpn.net","host":"91.132.137.170","public_key":"6/tjvgb7HFl7UuvBSegolxa1zKr3iSlDrlCexCmhAGE=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":21210},{"hostname":"us-ny2.wg.ivpn.net","host":"212.103.48.195","public_key":"c7DwY2uT+6ulWAJ5u8qJNWHroA0qyJLcdNzf/f2kkhs=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":21801},{"hostname":"us-ny3.wg.ivpn.net","host":"89.187.178.145","public_key":"m5/Ssw9SN3WuE+yD/fAsH5G8iuI8TcDGEiZZnPgiMCc=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":27601}]},{"gateway":"se.wg.ivpn.net","country_code":"SE","country":"Sweden","city":"Stockholm","latitude":59.3508,"longitude":18.0973,"isp":"M247","hosts":[{"hostname":"se1.wg.ivpn.net","host":"37.120.153.226","public_key":"2n0nFE1g/+vQr2AOQPm9Igyiy0zh9uTTultvOOSkMRo=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":24010},{"hostname":"se01.wg.ivpn.net","host":"80.67.10.141","public_key":"u8VHnYEpoEjJWDAF9NAUkU6s810RnkMuhEfFD9U0cGo=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":24001}]},{"gateway":"sg.wg.ivpn.net","country_code":"SG","country":"Singapore","city":"Singapore","latitude":1.293,"longitude":103.8558,"isp":"M247","hosts":[{"hostname":"sg1.wg.ivpn.net","host":"37.120.151.122","public_key":"hSg0At4uwuIhmTy5UT4fRbi5AN6JO2ZWTuIvqd4nHCE=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":26110},{"hostname":"sg01.wg.ivpn.net","host":"185.128.24.189","public_key":"pWk0u1Xq8FHC+xpkN+C6yEKOTEanorR5zMCSfHlLzFw=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":26101}]},{"gateway":"ch.wg.ivpn.net","country_code":"CH","country":"Switzerland","city":"Zurich","latitude":47.38,"longitude":8.55,"isp":"Privatelayer","hosts":[{"hostname":"ch1.wg.ivpn.net","host":"141.255.164.66","public_key":"jVZJ61i1xxkAfriDHpwvF/GDuTvZUqhwoWSjkOJvaUA=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":23610},{"hostname":"ch3.wg.ivpn.net","host":"141.255.166.198","public_key":"JBpgBKtqIneRuEga7mbP2PAk/e4HPRaC11H0A0+R3lA=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":22901},{"hostname":"ch01.wg.ivpn.net","host":"185.212.170.141","public_key":"dU7gLfcupYd37LW0q6cxC6PHMba+eUFAUOoU/ryXZkY=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":23601}]},{"gateway":"it.wg.ivpn.net","country_code":"IT","country":"Italy","city":"Milan","latitude":45.47,"longitude":9.205,"isp":"M247","hosts":[{"hostname":"it1.wg.ivpn.net","host":"82.102.21.90","public_key":"Aj6b81yrDk7I913R+fuSW/NAmIl87N73vHgY5/WQY0Q=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":24310},{"hostname":"it01.wg.ivpn.net","host":"158.58.172.89","public_key":"QTzR5R6jeDI/cQ0CXPIqOby9GR5nn+4Bcf4bK536Vy0=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":24301}]},{"gateway":"ro.wg.ivpn.net","country_code":"RO","country":"Romania","city":"Bucharest","latitude":44.4334,"longitude":26.0999,"isp":"M247","hosts":[{"hostname":"ro1.wg.ivpn.net","host":"37.120.206.53","public_key":"F2uQ57hysZTlw8WYELnyCw9Lga80wNYoYwkrrxyXKmw=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":22301}]},{"gateway":"fr.wg.ivpn.net","country_code":"FR","country":"France","city":"Paris","latitude":48.8667,"longitude":2.3333,"isp":"Datapacket","hosts":[{"hostname":"fr1.wg.ivpn.net","host":"185.246.211.185","public_key":"g7BuMzj3r/noLiLR4qhQMcvU6GSIY8RGEnaYtdYsFX4=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":23401}]},{"gateway":"is.wg.ivpn.net","country_code":"IS","country":"Iceland","city":"Reykjavik","latitude":64.15,"longitude":-21.95,"isp":"Advania","hosts":[{"hostname":"is1.wg.ivpn.net","host":"82.221.107.185","public_key":"nZZT6TlQ2dXlVe3P3B5ozEScHYMWH4JY4y3to8w5dz0=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":23501}]},{"gateway":"hk.wg.ivpn.net","country_code":"HK","country":"Hong Kong","city":"Hong Kong","latitude":22.305,"longitude":114.185,"isp":"Leaseweb","hosts":[{"hostname":"hk1.wg.ivpn.net","host":"209.58.189.105","public_key":"MbqqGy6TI2WVxHYdMa7X1LJoIEQNElhYXMGlMqtwtS0=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":23301},{"hostname":"hk2.wg.ivpn.net","host":"64.120.120.239","public_key":"kyolyq4cJydI3vQB2ESTIUAy2Fq0bpOf+Qe7GIq6XEA=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":27501}]},{"gateway":"us-ut.wg.ivpn.net","country_code":"US","country":"United States","city":"Salt Lake City, UT","latitude":40.7774,"longitude":-111.93,"isp":"100TB","hosts":[{"hostname":"us-ut1.wg.ivpn.net","host":"206.190.145.92","public_key":"KirI7bpxD186CuYiOqNHF+QUe6YmRYf6CN3pXWOJT2k=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":24401}]},{"gateway":"us-fl.wg.ivpn.net","country_code":"US","country":"United States","city":"Miami, FL","latitude":25.7839,"longitude":-80.2102,"isp":"Quadranet","hosts":[{"hostname":"us-fl1.wg.ivpn.net","host":"173.44.49.93","public_key":"Rkzo9WgxJBiKyEbkZvqGWtOVh9Gk9Vd7wL49SHXdHig=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":24601}]},{"gateway":"ca.wg.ivpn.net","country_code":"CA","country":"Canada","city":"Toronto","latitude":43.7,"longitude":-79.42,"isp":"Amanah","hosts":[{"hostname":"ca2.wg.ivpn.net","host":"172.86.186.173","public_key":"5qHV10ZbFgEGnF6wg9QpKeh1l6Di2JUG/5PdNaaoNW8=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":22101},{"hostname":"ca01.wg.ivpn.net","host":"104.254.90.181","public_key":"mdGnCZwinuOVGg46zsWnFhhenfFId6jht9GBTKB+xUA=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":23801}]},{"gateway":"us-nj.wg.ivpn.net","country_code":"US","country":"United States","city":"New Jersey, NJ","latitude":40.737764,"longitude":-74.151747,"isp":"Quadranet","hosts":[{"hostname":"us-nj3.wg.ivpn.net","host":"23.226.128.21","public_key":"AX7C1LO0ECUcHRYgX4/tIDYdR8npvfB/+pf4AfI3OHU=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":21610},{"hostname":"us-nj4.wg.ivpn.net","host":"194.36.111.54","public_key":"1Te4AfL1yKo2k4jzPALnRPfKE3YSzXKo4XIRHPz5FxI=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":27401}]},{"gateway":"es.wg.ivpn.net","country_code":"ES","country":"Spain","city":"Madrid","latitude":40.4,"longitude":-3.6834,"isp":"Datapacket","hosts":[{"hostname":"es1.wg.ivpn.net","host":"84.17.62.98","public_key":"w7umiArTtlJ4Pk6Ii9WX5VXK5vw/Qu+Z37/icKlIYWo=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":21501}]},{"gateway":"pl.wg.ivpn.net","country_code":"PL","country":"Poland","city":"Warsaw","latitude":52.25,"longitude":21,"isp":"Datapacket","hosts":[{"hostname":"pl1.wg.ivpn.net","host":"185.246.208.109","public_key":"1JDmF79rWj5C+kHp71AbdHne/yGaizWCd2bLfSFvYjo=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":25101}]},{"gateway":"cz.wg.ivpn.net","country_code":"CZ","country":"Czech Republic","city":"Prague","latitude":50.0833,"longitude":14.466,"isp":"Datapacket","hosts":[{"hostname":"cz1.wg.ivpn.net","host":"185.180.14.41","public_key":"gVbEq2cGRzwCSGPqT2oRSYYN+P6IK3uvvRffErASDSk=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":25201}]},{"gateway":"no.wg.ivpn.net","country_code":"NO","country":"Norway","city":"Oslo","latitude":59.9167,"longitude":10.75,"isp":"Servetheworld","hosts":[{"hostname":"no1.wg.ivpn.net","host":"91.189.177.156","public_key":"xFO6ksbO3Gr05rRgAW0O5Veoi4bpTgz2G9RvtBzK7Cg=","local_ip":"172.16.0.1/12","ipv6":{},"multihop_port":25301}]},{"gateway":"hu.wg.ivpn.net","country_code":"HU","country":"Hungary","city":"Budapest","latitude":47.5,"longitude":19.0833,"isp":"M247","hosts":[{"hostname":"hu1.wg.ivpn.net","host":"185.189.114.189","public_key":"G30fNdXrnlqtqqOLF23QXWzFdLIKDxLW60HoYPvqml8=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":25401}]},{"gateway":"dk.wg.ivpn.net","country_code":"DK","country":"Denmark","city":"Copenhagen","latitude":55.6786,"longitude":12.5635,"isp":"M247","hosts":[{"hostname":"dk1.wg.ivpn.net","host":"185.245.84.229","public_key":"jTsV5gOD7lT4egDj9rhKwO2OO2X7bKs2EQPcZEnUWDE=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":25501}]},{"gateway":"at.wg.ivpn.net","country_code":"AT","country":"Austria","city":"Vienna","latitude":48.2,"longitude":16.3666,"isp":"M247","hosts":[{"hostname":"at1.wg.ivpn.net","host":"185.244.212.69","public_key":"83LUBnP97SFpnS0y1MpEAFcg8MIiQJgW1FRv/8Mc40g=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":25601}]},{"gateway":"be.wg.ivpn.net","country_code":"BE","country":"Belgium","city":"Brussels","latitude":50.8333,"longitude":4.3333,"isp":"M247","hosts":[{"hostname":"be1.wg.ivpn.net","host":"194.187.251.13","public_key":"awriP5lpdxEMWKuG+A1DOg+vb1M5jd3WhynIMB61BhU=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":25701}]},{"gateway":"bg.wg.ivpn.net","country_code":"BG","country":"Bulgaria","city":"Sofia","latitude":42.6833,"longitude":23.3167,"isp":"M247","hosts":[{"hostname":"bg1.wg.ivpn.net","host":"82.102.23.21","public_key":"WDSsdJE6wvATIWfzQwayPtE/0DaXBQgW/hPm7sQSJmU=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":25901}]},{"gateway":"sk.wg.ivpn.net","country_code":"SK","country":"Slovakia","city":"Bratislava","latitude":48.15,"longitude":17.117,"isp":"M247","hosts":[{"hostname":"sk1.wg.ivpn.net","host":"185.245.85.253","public_key":"MOBWWpEgNsKbFj4BEyWSDFLlkBs5iUFiqdSdTFTDBko=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":25801}]},{"gateway":"jp.wg.ivpn.net","country_code":"JP","country":"Japan","city":"Tokyo","latitude":35.685,"longitude":139.7514,"isp":"M247","hosts":[{"hostname":"jp1.wg.ivpn.net","host":"91.207.174.237","public_key":"tb9WdC3LSho3d1rI5N7kfG9e42/d+u4LPVdEYERPsSQ=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":26201}]},{"gateway":"ua.wg.ivpn.net","country_code":"UA","country":"Ukraine","city":"Kharkiv","latitude":50,"longitude":36.25,"isp":"Xservers","hosts":[{"hostname":"ua1.wg.ivpn.net","host":"176.103.57.129","public_key":"mIxEzfjZ2wV6jJVj30w38ECd2LSH4bw/HLMnM2ICHiI=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":26301}]},{"gateway":"fi.wg.ivpn.net","country_code":"FI","country":"Finland","city":"Helsinki","latitude":60.1756,"longitude":24.9341,"isp":"Creanova","hosts":[{"hostname":"fi1.wg.ivpn.net","host":"194.34.134.63","public_key":"mIxEzfjZ2wV6jJVj30w38ECd2LSH4bw/HLMnM2ICHiI=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":26001}]},{"gateway":"us-az.wg.ivpn.net","country_code":"US","country":"United States","city":"Phoenix, AZ","latitude":33.5722,"longitude":-112.0891,"isp":"M247","hosts":[{"hostname":"us-az1.wg.ivpn.net","host":"193.37.254.133","public_key":"Ts4MGazxpxL9rrYbERjgxa+kCEX85ou9gHoaJvDsRiI=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":26401}]},{"gateway":"us-nv.wg.ivpn.net","country_code":"US","country":"United States","city":"Las Vegas, NV","latitude":36.2333,"longitude":-115.2654,"isp":"M247","hosts":[{"hostname":"us-nv1.wg.ivpn.net","host":"185.242.5.37","public_key":"PRpvAZyoNWNm/KHlqafjtYoZtn1PkIPylUE4WbuYmgM=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":26501}]},{"gateway":"au-nsw.wg.ivpn.net","country_code":"AU","country":"Australia","city":"Sydney","latitude":-33.92,"longitude":151.1852,"isp":"M247","hosts":[{"hostname":"au-nsw1.wg.ivpn.net","host":"46.102.153.246","public_key":"KmSrG48t5xw9CJCPlYLBG3JnmiY0CnUgyRM5TUEwZhM=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":26601},{"hostname":"au-nsw2.wg.ivpn.net","host":"146.70.78.75","public_key":"q+wbp7GjiTszp5G16rNpGCqxkL0qSY3CH4pcgD6UsVQ=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":27801}]},{"gateway":"br.wg.ivpn.net","country_code":"BR","country":"Brazil","city":"Franca","latitude":-20.53,"longitude":-47.39,"isp":"Qnax","hosts":[{"hostname":"br1.wg.ivpn.net","host":"45.162.229.133","public_key":"eN1f15S3YzRyYCALiPGRQcjkQO9xntcdqPhJJ6TOymc=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":26701}]},{"gateway":"rs.wg.ivpn.net","country_code":"RS","country":"Serbia","city":"Belgrade","latitude":44.8186,"longitude":20.468,"isp":"M247","hosts":[{"hostname":"rs1.wg.ivpn.net","host":"141.98.103.253","public_key":"xLN/lpQThQ3z3tvYf7VqdAsRL/nton1Vhv2kCZlQtWE=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":26801}]},{"gateway":"gb-man.wg.ivpn.net","country_code":"GB","country":"United Kingdom","city":"Manchester","latitude":53.5004,"longitude":-2.248,"isp":"M247","hosts":[{"hostname":"gb-man1.wg.ivpn.net","host":"89.238.141.231","public_key":"+hf4DYilNEIjTdSOuCNcWdqVyaRoxGzXw7wvNl7f7Rg=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":26901}]},{"gateway":"pt.wg.ivpn.net","country_code":"PT","country":"Portugal","city":"Lisbon","latitude":38.7227,"longitude":-9.1449,"isp":"Hostwebis","hosts":[{"hostname":"pt1.wg.ivpn.net","host":"94.46.175.113","public_key":"nMnA82YVrvEK80GVoY/0Z9McWeqjcLzuMYSL+86j5nU=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":27101}]},{"gateway":"lu.wg.ivpn.net","country_code":"LU","country":"Luxembourg","city":"Luxembourg","latitude":49.6117,"longitude":6.13,"isp":"Evoluso","hosts":[{"hostname":"lu1.wg.ivpn.net","host":"92.223.89.57","public_key":"hUS1OAFLGwpba8+oc5mifYtohZt/RTro5dMyYBLYHjI=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":27201}]},{"gateway":"il.wg.ivpn.net","country_code":"IL","country":"Israel","city":"Holon, Tel Aviv","latitude":32.08,"longitude":34.77,"isp":"HQServ","hosts":[{"hostname":"il01.wg.ivpn.net","host":"185.191.207.197","public_key":"HR9gAjpxXU3YVt6kehBw5n8yVYVE0iIgJdc4HTqOzEE=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":27301}]},{"gateway":"us-va.wg.ivpn.net","country_code":"US","country":"United States","city":"Ashburn, VA","latitude":39.0437,"longitude":-77.4875,"isp":"Datapacket","hosts":[{"hostname":"us-va1.wg.ivpn.net","host":"37.19.206.106","public_key":"ZCnZK6U+cRuP/WgzIDb/P6UG2rX/KyCRd5vJ1hAbr2E=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":27701}]},{"gateway":"us-wa.wg.ivpn.net","country_code":"US","country":"United States","city":"Seattle, WA","latitude":47.6211,"longitude":-122.3244,"isp":"Tzulo","hosts":[{"hostname":"us-wa2.wg.ivpn.net","host":"198.44.131.4","public_key":"VcrOOozBUCIURU0AnqMAE7AkMmC7Qrp+j/PzPbgbalU=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"multihop_port":27801}]}],"openvpn":[{"gateway":"us-ca.gw.ivpn.net","country_code":"US","country":"United States","city":"Los Angeles, CA","latitude":34.1139,"longitude":-118.4068,"isp":"Quadranet","hosts":[{"hostname":"us-ca1.gw.ivpn.net","host":"173.254.196.58","multihop_port":22201},{"hostname":"us-ca2.gw.ivpn.net","host":"69.12.80.146","multihop_port":22401},{"hostname":"us-ca3.gw.ivpn.net","host":"198.54.129.99","multihop_port":21301},{"hostname":"us-ca4.gw.ivpn.net","host":"173.254.204.202","multihop_port":21901}]},{"gateway":"ro.gw.ivpn.net","country_code":"RO","country":"Romania","city":"Bucharest","latitude":44.4334,"longitude":26.0999,"isp":"M247","hosts":[{"hostname":"ro1.gw.ivpn.net","host":"37.120.206.50","multihop_port":22301}]},{"gateway":"de.gw.ivpn.net","country_code":"DE","country":"Germany","city":"Frankfurt","latitude":50.1,"longitude":8.675,"isp":"Leaseweb","hosts":[{"hostname":"de1.gw.ivpn.net","host":"178.162.222.40","multihop_port":23001},{"hostname":"de2.gw.ivpn.net","host":"178.162.211.114","multihop_port":22001}]},{"gateway":"nl.gw.ivpn.net","country_code":"NL","country":"Netherlands","city":"Amsterdam","latitude":52.35,"longitude":4.9166,"isp":"Leaseweb","hosts":[{"hostname":"nl4.gw.ivpn.net","host":"95.211.172.95","multihop_port":23201},{"hostname":"nl3.gw.ivpn.net","host":"95.211.172.68","multihop_port":23101},{"hostname":"nl6.gw.ivpn.net","host":"95.211.187.228","multihop_port":24101},{"hostname":"nl5.gw.ivpn.net","host":"95.211.187.222","multihop_port":23901},{"hostname":"nl7.gw.ivpn.net","host":"95.211.95.22","multihop_port":22501},{"hostname":"nl8.gw.ivpn.net","host":"95.211.172.18","multihop_port":22801}]},{"gateway":"fr.gw.ivpn.net","country_code":"FR","country":"France","city":"Paris","latitude":48.8667,"longitude":2.3333,"isp":"Datapacket","hosts":[{"hostname":"fr1.gw.ivpn.net","host":"185.246.211.179","multihop_port":23401}]},{"gateway":"is.gw.ivpn.net","country_code":"IS","country":"Iceland","city":"Reykjavik","latitude":64.15,"longitude":-21.95,"isp":"Advania","hosts":[{"hostname":"is1.gw.ivpn.net","host":"82.221.107.178","multihop_port":23501}]},{"gateway":"hk.gw.ivpn.net","country_code":"HK","country":"Hong Kong","city":"Hong Kong","latitude":22.305,"longitude":114.185,"isp":"Leaseweb","hosts":[{"hostname":"hk1.gw.ivpn.net","host":"209.58.189.163","multihop_port":23301},{"hostname":"hk2.gw.ivpn.net","host":"209.58.188.13","multihop_port":27501}]},{"gateway":"us-tx.gw.ivpn.net","country_code":"US","country":"United States","city":"Dallas, TX","latitude":32.7936,"longitude":-96.7662,"isp":"Quadranet","hosts":[{"hostname":"us-tx1.gw.ivpn.net","host":"96.44.189.194","multihop_port":21001},{"hostname":"us-tx2.gw.ivpn.net","host":"96.44.142.74","multihop_port":25001}]},{"gateway":"gb.gw.ivpn.net","country_code":"GB","country":"United Kingdom","city":"London","latitude":51.5,"longitude":-0.1167,"isp":"Datapacket","hosts":[{"hostname":"gb2.gw.ivpn.net","host":"185.59.221.88","multihop_port":24201},{"hostname":"gb1.gw.ivpn.net","host":"185.59.221.133","multihop_port":20801}]},{"gateway":"us-ut.gw.ivpn.net","country_code":"US","country":"United States","city":"Salt Lake City, UT","latitude":40.7774,"longitude":-111.93,"isp":"100TB","hosts":[{"hostname":"us-ut1.gw.ivpn.net","host":"198.105.216.28","multihop_port":24401}]},{"gateway":"it.gw.ivpn.net","country_code":"IT","country":"Italy","city":"Milan","latitude":45.47,"longitude":9.205,"isp":"SEFlow","hosts":[{"hostname":"it1.gw.ivpn.net","host":"158.58.172.73","multihop_port":24301}]},{"gateway":"se.gw.ivpn.net","country_code":"SE","country":"Sweden","city":"Stockholm","latitude":59.3508,"longitude":18.0973,"isp":"GleSyS","hosts":[{"hostname":"se1.gw.ivpn.net","host":"80.67.10.138","multihop_port":24001}]},{"gateway":"us-ga.gw.ivpn.net","country_code":"US","country":"United States","city":"Atlanta, GA","latitude":33.7627,"longitude":-84.4225,"isp":"Quadranet","hosts":[{"hostname":"us-ga1.gw.ivpn.net","host":"104.129.24.146","multihop_port":24501},{"hostname":"us-ga2.gw.ivpn.net","host":"107.150.22.74","multihop_port":24810}]},{"gateway":"us-fl.gw.ivpn.net","country_code":"US","country":"United States","city":"Miami, FL","latitude":25.7839,"longitude":-80.2102,"isp":"Quadranet","hosts":[{"hostname":"us-fl1.gw.ivpn.net","host":"173.44.49.90","multihop_port":24601}]},{"gateway":"ca.gw.ivpn.net","country_code":"CA","country":"Canada","city":"Toronto","latitude":43.7,"longitude":-79.42,"isp":"Amanah","hosts":[{"hostname":"ca2.gw.ivpn.net","host":"172.86.186.170","multihop_port":22101},{"hostname":"ca1.gw.ivpn.net","host":"104.254.90.178","multihop_port":23801}]},{"gateway":"ch.gw.ivpn.net","country_code":"CH","country":"Switzerland","city":"Zurich","latitude":47.38,"longitude":8.55,"isp":"Privatelayer","hosts":[{"hostname":"ch3.gw.ivpn.net","host":"141.255.166.194","multihop_port":22901},{"hostname":"ch1.gw.ivpn.net","host":"185.212.170.138","multihop_port":23601}]},{"gateway":"us-il.gw.ivpn.net","country_code":"US","country":"United States","city":"Chicago, IL","latitude":41.8373,"longitude":-87.6862,"isp":"Quadranet","hosts":[{"hostname":"us-il1.gw.ivpn.net","host":"107.150.28.82","multihop_port":21401},{"hostname":"us-il2.gw.ivpn.net","host":"72.11.137.146","multihop_port":24901}]},{"gateway":"us-nj.gw.ivpn.net","country_code":"US","country":"United States","city":"New Jersey, NJ","latitude":40.737764,"longitude":-74.151747,"isp":"Quadranet","hosts":[{"hostname":"us-nj3.gw.ivpn.net","host":"23.226.128.18","multihop_port":21610},{"hostname":"us-nj4.gw.ivpn.net","host":"194.36.111.50","multihop_port":27401}]},{"gateway":"es.gw.ivpn.net","country_code":"ES","country":"Spain","city":"Madrid","latitude":40.4,"longitude":-3.6834,"isp":"Datapacket","hosts":[{"hostname":"es1.gw.ivpn.net","host":"185.93.3.193","multihop_port":21501}]},{"gateway":"us-ny.gw.ivpn.net","country_code":"US","country":"United States","city":"New York, NY","latitude":40.6943,"longitude":-73.9249,"isp":"M247","hosts":[{"hostname":"us-ny2.gw.ivpn.net","host":"212.103.48.194","multihop_port":21801},{"hostname":"us-ny3.gw.ivpn.net","host":"89.187.178.144","multihop_port":27601}]},{"gateway":"pl.gw.ivpn.net","country_code":"PL","country":"Poland","city":"Warsaw","latitude":52.25,"longitude":21,"isp":"Datapacket","hosts":[{"hostname":"pl1.gw.ivpn.net","host":"185.246.208.86","multihop_port":25101}]},{"gateway":"cz.gw.ivpn.net","country_code":"CZ","country":"Czech Republic","city":"Prague","latitude":50.0833,"longitude":14.466,"isp":"Datapacket","hosts":[{"hostname":"cz1.gw.ivpn.net","host":"195.181.160.167","multihop_port":25201}]},{"gateway":"no.gw.ivpn.net","country_code":"NO","country":"Norway","city":"Oslo","latitude":59.9167,"longitude":10.75,"isp":"Servetheworld","hosts":[{"hostname":"no1.gw.ivpn.net","host":"194.242.10.150","multihop_port":25301}]},{"gateway":"hu.gw.ivpn.net","country_code":"HU","country":"Hungary","city":"Budapest","latitude":47.5,"longitude":19.0833,"isp":"M247","hosts":[{"hostname":"hu1.gw.ivpn.net","host":"185.189.114.186","multihop_port":25401}]},{"gateway":"dk.gw.ivpn.net","country_code":"DK","country":"Denmark","city":"Copenhagen","latitude":55.6786,"longitude":12.5635,"isp":"M247","hosts":[{"hostname":"dk1.gw.ivpn.net","host":"185.245.84.226","multihop_port":25501}]},{"gateway":"at.gw.ivpn.net","country_code":"AT","country":"Austria","city":"Vienna","latitude":48.2,"longitude":16.3666,"isp":"M247","hosts":[{"hostname":"at1.gw.ivpn.net","host":"185.244.212.66","multihop_port":25601}]},{"gateway":"be.gw.ivpn.net","country_code":"BE","country":"Belgium","city":"Brussels","latitude":50.8333,"longitude":4.3333,"isp":"M247","hosts":[{"hostname":"be1.gw.ivpn.net","host":"194.187.251.10","multihop_port":25701}]},{"gateway":"bg.gw.ivpn.net","country_code":"BG","country":"Bulgaria","city":"Sofia","latitude":42.6833,"longitude":23.3167,"isp":"M247","hosts":[{"hostname":"bg1.gw.ivpn.net","host":"82.102.23.18","multihop_port":25901}]},{"gateway":"sk.gw.ivpn.net","country_code":"SK","country":"Slovakia","city":"Bratislava","latitude":48.15,"longitude":17.117,"isp":"M247","hosts":[{"hostname":"sk1.gw.ivpn.net","host":"185.245.85.250","multihop_port":25801}]},{"gateway":"jp.gw.ivpn.net","country_code":"JP","country":"Japan","city":"Tokyo","latitude":35.685,"longitude":139.7514,"isp":"M247","hosts":[{"hostname":"jp1.gw.ivpn.net","host":"91.207.174.234","multihop_port":26201}]},{"gateway":"sg.gw.ivpn.net","country_code":"SG","country":"Singapore","city":"Singapore","latitude":1.293,"longitude":103.8558,"isp":"M247","hosts":[{"hostname":"sg1.gw.ivpn.net","host":"185.128.24.186","multihop_port":26101}]},{"gateway":"ua.gw.ivpn.net","country_code":"UA","country":"Ukraine","city":"Kharkiv","latitude":50,"longitude":36.25,"isp":"Xservers","hosts":[{"hostname":"ua1.gw.ivpn.net","host":"193.203.48.54","multihop_port":26301}]},{"gateway":"fi.gw.ivpn.net","country_code":"FI","country":"Finland","city":"Helsinki","latitude":60.1756,"longitude":24.9341,"isp":"Creanova","hosts":[{"hostname":"fi1.gw.ivpn.net","host":"185.112.82.12","multihop_port":26001}]},{"gateway":"us-az.gw.ivpn.net","country_code":"US","country":"United States","city":"Phoenix, AZ","latitude":33.5722,"longitude":-112.0891,"isp":"M247","hosts":[{"hostname":"us-az1.gw.ivpn.net","host":"193.37.254.130","multihop_port":26401}]},{"gateway":"us-nv.gw.ivpn.net","country_code":"US","country":"United States","city":"Las Vegas, NV","latitude":36.2333,"longitude":-115.2654,"isp":"M247","hosts":[{"hostname":"us-nv1.gw.ivpn.net","host":"185.242.5.34","multihop_port":26501}]},{"gateway":"au-nsw.gw.ivpn.net","country_code":"AU","country":"Australia","city":"Sydney","latitude":-33.92,"longitude":151.1852,"isp":"M247","hosts":[{"hostname":"au-nsw1.gw.ivpn.net","host":"46.102.153.242","multihop_port":26601},{"hostname":"au-nsw2.gw.ivpn.net","host":"146.70.78.74","multihop_port":27801}]},{"gateway":"br.gw.ivpn.net","country_code":"BR","country":"Brazil","city":"Franca","latitude":-20.53,"longitude":-47.39,"isp":"Qnax","hosts":[{"hostname":"br1.gw.ivpn.net","host":"45.162.229.130","multihop_port":26701}]},{"gateway":"rs.gw.ivpn.net","country_code":"RS","country":"Serbia","city":"Belgrade","latitude":44.8186,"longitude":20.468,"isp":"M247","hosts":[{"hostname":"rs1.gw.ivpn.net","host":"141.98.103.250","multihop_port":26801}]},{"gateway":"gb-man.gw.ivpn.net","country_code":"GB","country":"United Kingdom","city":"Manchester","latitude":53.5004,"longitude":-2.248,"isp":"M247","hosts":[{"hostname":"gb-man1.gw.ivpn.net","host":"89.238.141.228","multihop_port":26901}]},{"gateway":"ca-qc.gw.ivpn.net","country_code":"CA","country":"Canada","city":"Montreal","latitude":45.5,"longitude":-73.5833,"isp":"M247","hosts":[{"hostname":"ca-qc1.gw.ivpn.net","host":"87.101.92.26","multihop_port":27001}]},{"gateway":"pt.gw.ivpn.net","country_code":"PT","country":"Portugal","city":"Lisbon","latitude":38.7227,"longitude":-9.1449,"isp":"Hostwebis","hosts":[{"hostname":"pt1.gw.ivpn.net","host":"94.46.175.112","multihop_port":27101}]},{"gateway":"lu.gw.ivpn.net","country_code":"LU","country":"Luxembourg","city":"Luxembourg","latitude":49.6117,"longitude":6.13,"isp":"Evoluso","hosts":[{"hostname":"lu1.gw.ivpn.net","host":"92.223.89.53","multihop_port":27201}]},{"gateway":"il.gw.ivpn.net","country_code":"IL","country":"Israel","city":"Holon, Tel Aviv","latitude":32.08,"longitude":34.77,"isp":"HQServ","hosts":[{"hostname":"il1.gw.ivpn.net","host":"185.191.207.194","multihop_port":27301}]},{"gateway":"us-va.gw.ivpn.net","country_code":"US","country":"United States","city":"Ashburn, VA","latitude":39.0437,"longitude":-77.4875,"isp":"Datapacket","hosts":[{"hostname":"us-va1.gw.ivpn.net","host":"37.19.206.105","multihop_port":27701}]},{"gateway":"us-wa.gw.ivpn.net","country_code":"US","country":"United States","city":"Seattle, WA","latitude":47.6211,"longitude":-122.3244,"isp":"Tzulo","hosts":[{"hostname":"us-wa2.gw.ivpn.net","host":"198.44.131.3","multihop_port":27801}]}],"config":{"antitracker":{"default":{"ip":"10.0.254.2","multihop-ip":"10.0.254.102"},"hardcore":{"ip":"10.0.254.3","multihop-ip":"10.0.254.103"}},"api":{"ips":["198.50.177.220","198.50.177.222","198.50.177.223"],"ipv6s":["2607:5300:203:1735::8888","2607:5300:203:1735::8","2607:5300:203:1735:6580:7300:0:aaaa"]}}}
+{"wireguard":[{"gateway":"us-tx.wg.ivpn.net","country_code":"US","country":"United States","city":"Dallas, TX","latitude":32.7936,"longitude":-96.7662,"isp":"Quadranet","hosts":[{"hostname":"us-tx1.wg.ivpn.net","host":"198.55.124.114","public_key":"JPT1veXLmasj2uQDstX24mpR7VWD+GmV8JDkidkz91Q=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":9.1,"multihop_port":21010},{"hostname":"us-tx01.wg.ivpn.net","host":"96.44.189.197","public_key":"LvWf548mFddi8PTrIGL6uD1/l85LU8z0Rc8tpvw2Vls=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":15.49,"multihop_port":21001},{"hostname":"us-tx2.wg.ivpn.net","host":"96.44.142.77","public_key":"om8hOGUcEvoOhHvJZoBHxNF4jxY/+Ml9Iy1WOSC/pFo=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":9.84,"multihop_port":25001}]},{"gateway":"nl.wg.ivpn.net","country_code":"NL","country":"Netherlands","city":"Amsterdam","latitude":52.35,"longitude":4.9166,"isp":"Datapacket","hosts":[{"hostname":"nl1.wg.ivpn.net","host":"185.102.218.104","public_key":"AsMT2FqpkZbjzWeDch6GwufF5odl259W/hIkGytVfWo=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":13.92,"multihop_port":20301},{"hostname":"nl4.wg.ivpn.net","host":"95.211.95.19","public_key":"cVB66gPq5cZ9dfXY+e2pbsCyih5o1zk04l5c5VCsV1g=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":15.89,"multihop_port":23201},{"hostname":"nl3.wg.ivpn.net","host":"95.211.95.9","public_key":"XDU6Syq1DY82IMatsHV0x/TAtbLiRwh/SdFCXlEn40c=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":6.67,"multihop_port":23101},{"hostname":"nl6.wg.ivpn.net","host":"95.211.243.182","public_key":"hMWpqb3FEATHIbImPVWB/5z2nWIXghwpnJjevPY+1H0=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":20.91,"multihop_port":24101},{"hostname":"nl5.wg.ivpn.net","host":"95.211.243.162","public_key":"NCagAawwRixI6Iw/NWiGD8lbjDNCl0aTICZKJtO/1HA=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":40.56,"multihop_port":23901},{"hostname":"nl7.wg.ivpn.net","host":"95.211.172.105","public_key":"hQNYqtfOOAEz0IGshLx/TI9hUrfR9gIIkjVm4VsCbBM=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":8.57,"multihop_port":22501},{"hostname":"nl8.wg.ivpn.net","host":"95.211.198.167","public_key":"/nY1/OhVhdHtbnU/s31zYUuPBH0pizv4DemW5KDOUkg=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":21.1,"multihop_port":22801}]},{"gateway":"de.wg.ivpn.net","country_code":"DE","country":"Germany","city":"Frankfurt","latitude":50.1,"longitude":8.675,"isp":"Datapacket","hosts":[{"hostname":"de1.wg.ivpn.net","host":"185.102.219.26","public_key":"mS3/WpXjnMAMmXjSpd4nFzx9HSE3ubv2WyjpyH2REgs=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":35.67,"multihop_port":23010},{"hostname":"de01.wg.ivpn.net","host":"178.162.212.24","public_key":"Sc5AUZieg0qX8kyCy9p0OHRES4n0CHtHHM+ZPyERFTc=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":25.53,"multihop_port":23001},{"hostname":"de2.wg.ivpn.net","host":"37.58.60.151","public_key":"QhY3OtBf4FFafKtLO33e6k8JnAl8e6ktFcRUyLjCDVY=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":9.54,"multihop_port":22001}]},{"gateway":"us-il.wg.ivpn.net","country_code":"US","country":"United States","city":"Chicago, IL","latitude":41.8373,"longitude":-87.6862,"isp":"Datapacket","hosts":[{"hostname":"us-il1.wg.ivpn.net","host":"89.187.181.116","public_key":"hku9gjamhoii8OvxZgx+TdUDIkOAQYFu39qbav2AyUQ=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":12.03,"multihop_port":21410},{"hostname":"us-il01.wg.ivpn.net","host":"72.11.137.158","public_key":"Uy5a8JOqneAUY1dC5s9jubLnotbyIfBsLP2nZuzRbHs=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":14.63,"multihop_port":21401},{"hostname":"us-il2.wg.ivpn.net","host":"72.11.137.148","public_key":"ANhVUMAQgStPVNRHW8mg0ZtN1YI1QHyXfNCO8+USNQQ=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":11.84,"multihop_port":24901}]},{"gateway":"us-ga.wg.ivpn.net","country_code":"US","country":"United States","city":"Atlanta, GA","latitude":33.7627,"longitude":-84.4225,"isp":"Datapacket","hosts":[{"hostname":"us-ga1.wg.ivpn.net","host":"185.93.0.212","public_key":"jD8h+pL5/d6fmYcTzl0lR8AWzQVN5XkwRFSmM/3NcDM=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":8.42,"multihop_port":24510},{"hostname":"us-ga01.wg.ivpn.net","host":"104.129.24.149","public_key":"EJFl28aYpZKfmJqb1jxxTEnGx6kaH2USVrigpHKKXhs=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":30.84,"multihop_port":24501},{"hostname":"us-ga2.wg.ivpn.net","host":"107.150.22.77","public_key":"hr2uQOEGCvGeDkoCQJ2dCI8dM8Iu5aKhb1PIvJ9q72E=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":8.51,"multihop_port":24810}]},{"gateway":"us-ca.wg.ivpn.net","country_code":"US","country":"United States","city":"Los Angeles, CA","latitude":34.1139,"longitude":-118.4068,"isp":"Datapacket","hosts":[{"hostname":"us-ca1.wg.ivpn.net","host":"185.180.13.41","public_key":"FGl78s9Ct6xNamQ2/CtAyXwGePrrU0kiZxfM27pm8XA=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":7.79,"multihop_port":22210},{"hostname":"us-ca01.wg.ivpn.net","host":"216.144.236.44","public_key":"B+qXdkIuETpzI0bfhGUAHN4SU91Tjs6ItdFlu93S42I=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":9.57,"multihop_port":22201},{"hostname":"us-ca2.wg.ivpn.net","host":"216.144.236.68","public_key":"qv4Tupfon5NUSwzDpM8zPizSwJZn2h+9CqrufcyDOko=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":7.08,"multihop_port":22401},{"hostname":"us-ca3.wg.ivpn.net","host":"198.54.129.100","public_key":"J5+Bx84LxNPdWEhewOvBV/fGWiDluIBlAcr1QlJZil8=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":13.68,"multihop_port":21301},{"hostname":"us-ca4.wg.ivpn.net","host":"216.144.237.83","public_key":"dYPXYr6HSRJPe3MhALwGWNtdEy1+EPE9Kqv7cTrUXk8=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":7.21,"multihop_port":21901}]},{"gateway":"ca-qc.wg.ivpn.net","country_code":"CA","country":"Canada","city":"Montreal","latitude":45.5,"longitude":-73.5833,"isp":"M247","hosts":[{"hostname":"ca1.wg.ivpn.net","host":"37.120.130.58","public_key":"rg+GGDmjM4Vxo1hURvKmgm9yonb6qcoKbPCP/DNDBnI=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":47.98,"multihop_port":23810},{"hostname":"ca-qc1.wg.ivpn.net","host":"87.101.92.29","public_key":"98JU1mdCR8vD1aNZg017/NjBeTjuuCKUaLw0zfz/CUE=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":50.12,"multihop_port":27001}]},{"gateway":"gb.wg.ivpn.net","country_code":"GB","country":"United Kingdom","city":"London","latitude":51.5,"longitude":-0.1167,"isp":"M247","hosts":[{"hostname":"gb1.wg.ivpn.net","host":"81.92.202.114","public_key":"7+jos+Eg+hMEOQE4Std6OJ+WVnCcmbqS1/EbPwn9w3s=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":6.26,"multihop_port":20810},{"hostname":"gb2.wg.ivpn.net","host":"185.59.221.225","public_key":"x0BTRaxsdxAd58ZyU2YMX4bmuj+Eg+8/urT2F3Vs1n8=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":7.16,"multihop_port":24201},{"hostname":"gb01.wg.ivpn.net","host":"185.59.221.140","public_key":"yKK5x+D17Jr3Q12T/UBaDjNVmNdZBsqpvTqH6YfsGHg=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":22.87,"multihop_port":20801}]},{"gateway":"us-ny.wg.ivpn.net","country_code":"US","country":"United States","city":"New York, NY","latitude":40.6943,"longitude":-73.9249,"isp":"M247","hosts":[{"hostname":"us-ny1.wg.ivpn.net","host":"91.132.137.170","public_key":"6/tjvgb7HFl7UuvBSegolxa1zKr3iSlDrlCexCmhAGE=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":9.23,"multihop_port":21210},{"hostname":"us-ny2.wg.ivpn.net","host":"212.103.48.195","public_key":"c7DwY2uT+6ulWAJ5u8qJNWHroA0qyJLcdNzf/f2kkhs=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":5.1,"multihop_port":21801},{"hostname":"us-ny3.wg.ivpn.net","host":"89.187.178.145","public_key":"m5/Ssw9SN3WuE+yD/fAsH5G8iuI8TcDGEiZZnPgiMCc=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":8.51,"multihop_port":27601}]},{"gateway":"se.wg.ivpn.net","country_code":"SE","country":"Sweden","city":"Stockholm","latitude":59.3508,"longitude":18.0973,"isp":"M247","hosts":[{"hostname":"se1.wg.ivpn.net","host":"37.120.153.226","public_key":"2n0nFE1g/+vQr2AOQPm9Igyiy0zh9uTTultvOOSkMRo=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":19.03,"multihop_port":24010},{"hostname":"se01.wg.ivpn.net","host":"80.67.10.141","public_key":"u8VHnYEpoEjJWDAF9NAUkU6s810RnkMuhEfFD9U0cGo=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":5.52,"multihop_port":24001}]},{"gateway":"sg.wg.ivpn.net","country_code":"SG","country":"Singapore","city":"Singapore","latitude":1.293,"longitude":103.8558,"isp":"M247","hosts":[{"hostname":"sg1.wg.ivpn.net","host":"37.120.151.122","public_key":"hSg0At4uwuIhmTy5UT4fRbi5AN6JO2ZWTuIvqd4nHCE=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":11.71,"multihop_port":26110},{"hostname":"sg01.wg.ivpn.net","host":"185.128.24.189","public_key":"pWk0u1Xq8FHC+xpkN+C6yEKOTEanorR5zMCSfHlLzFw=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":53.29,"multihop_port":26101}]},{"gateway":"ch.wg.ivpn.net","country_code":"CH","country":"Switzerland","city":"Zurich","latitude":47.38,"longitude":8.55,"isp":"Privatelayer","hosts":[{"hostname":"ch1.wg.ivpn.net","host":"141.255.164.66","public_key":"jVZJ61i1xxkAfriDHpwvF/GDuTvZUqhwoWSjkOJvaUA=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":21.76,"multihop_port":23610},{"hostname":"ch3.wg.ivpn.net","host":"141.255.166.198","public_key":"JBpgBKtqIneRuEga7mbP2PAk/e4HPRaC11H0A0+R3lA=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":20.08,"multihop_port":22901},{"hostname":"ch01.wg.ivpn.net","host":"185.212.170.141","public_key":"dU7gLfcupYd37LW0q6cxC6PHMba+eUFAUOoU/ryXZkY=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":54.97,"multihop_port":23601}]},{"gateway":"it.wg.ivpn.net","country_code":"IT","country":"Italy","city":"Milan","latitude":45.47,"longitude":9.205,"isp":"M247","hosts":[{"hostname":"it1.wg.ivpn.net","host":"82.102.21.90","public_key":"Aj6b81yrDk7I913R+fuSW/NAmIl87N73vHgY5/WQY0Q=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":6.64,"multihop_port":24310},{"hostname":"it01.wg.ivpn.net","host":"158.58.172.89","public_key":"QTzR5R6jeDI/cQ0CXPIqOby9GR5nn+4Bcf4bK536Vy0=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":12.37,"multihop_port":24301}]},{"gateway":"ro.wg.ivpn.net","country_code":"RO","country":"Romania","city":"Bucharest","latitude":44.4334,"longitude":26.0999,"isp":"M247","hosts":[{"hostname":"ro1.wg.ivpn.net","host":"37.120.206.53","public_key":"F2uQ57hysZTlw8WYELnyCw9Lga80wNYoYwkrrxyXKmw=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":47.19,"multihop_port":22301}]},{"gateway":"fr.wg.ivpn.net","country_code":"FR","country":"France","city":"Paris","latitude":48.8667,"longitude":2.3333,"isp":"Datapacket","hosts":[{"hostname":"fr1.wg.ivpn.net","host":"185.246.211.185","public_key":"g7BuMzj3r/noLiLR4qhQMcvU6GSIY8RGEnaYtdYsFX4=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":32.72,"multihop_port":23401}]},{"gateway":"is.wg.ivpn.net","country_code":"IS","country":"Iceland","city":"Reykjavik","latitude":64.15,"longitude":-21.95,"isp":"Advania","hosts":[{"hostname":"is1.wg.ivpn.net","host":"82.221.107.185","public_key":"nZZT6TlQ2dXlVe3P3B5ozEScHYMWH4JY4y3to8w5dz0=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":59.02,"multihop_port":23501}]},{"gateway":"us-ut.wg.ivpn.net","country_code":"US","country":"United States","city":"Salt Lake City, UT","latitude":40.7774,"longitude":-111.93,"isp":"100TB","hosts":[{"hostname":"us-ut1.wg.ivpn.net","host":"206.190.145.92","public_key":"KirI7bpxD186CuYiOqNHF+QUe6YmRYf6CN3pXWOJT2k=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":17.04,"multihop_port":24401}]},{"gateway":"us-fl.wg.ivpn.net","country_code":"US","country":"United States","city":"Miami, FL","latitude":25.7839,"longitude":-80.2102,"isp":"Quadranet","hosts":[{"hostname":"us-fl1.wg.ivpn.net","host":"173.44.49.93","public_key":"Rkzo9WgxJBiKyEbkZvqGWtOVh9Gk9Vd7wL49SHXdHig=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":13.74,"multihop_port":24601}]},{"gateway":"ca.wg.ivpn.net","country_code":"CA","country":"Canada","city":"Toronto","latitude":43.7,"longitude":-79.42,"isp":"Amanah","hosts":[{"hostname":"ca2.wg.ivpn.net","host":"172.86.186.173","public_key":"5qHV10ZbFgEGnF6wg9QpKeh1l6Di2JUG/5PdNaaoNW8=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":100,"multihop_port":22101},{"hostname":"ca01.wg.ivpn.net","host":"104.254.90.181","public_key":"mdGnCZwinuOVGg46zsWnFhhenfFId6jht9GBTKB+xUA=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":82.06,"multihop_port":23801}]},{"gateway":"us-nj.wg.ivpn.net","country_code":"US","country":"United States","city":"New Jersey, NJ","latitude":40.737764,"longitude":-74.151747,"isp":"Quadranet","hosts":[{"hostname":"us-nj3.wg.ivpn.net","host":"23.226.128.21","public_key":"AX7C1LO0ECUcHRYgX4/tIDYdR8npvfB/+pf4AfI3OHU=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":29.57,"multihop_port":21610},{"hostname":"us-nj4.wg.ivpn.net","host":"194.36.111.54","public_key":"1Te4AfL1yKo2k4jzPALnRPfKE3YSzXKo4XIRHPz5FxI=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":7.71,"multihop_port":27401}]},{"gateway":"es.wg.ivpn.net","country_code":"ES","country":"Spain","city":"Madrid","latitude":40.4,"longitude":-3.6834,"isp":"Datapacket","hosts":[{"hostname":"es1.wg.ivpn.net","host":"84.17.62.98","public_key":"w7umiArTtlJ4Pk6Ii9WX5VXK5vw/Qu+Z37/icKlIYWo=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":15.04,"multihop_port":21501}]},{"gateway":"pl.wg.ivpn.net","country_code":"PL","country":"Poland","city":"Warsaw","latitude":52.25,"longitude":21,"isp":"Datapacket","hosts":[{"hostname":"pl1.wg.ivpn.net","host":"185.246.208.109","public_key":"1JDmF79rWj5C+kHp71AbdHne/yGaizWCd2bLfSFvYjo=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":16.52,"multihop_port":25101}]},{"gateway":"cz.wg.ivpn.net","country_code":"CZ","country":"Czech Republic","city":"Prague","latitude":50.0833,"longitude":14.466,"isp":"Datapacket","hosts":[{"hostname":"cz1.wg.ivpn.net","host":"185.180.14.41","public_key":"gVbEq2cGRzwCSGPqT2oRSYYN+P6IK3uvvRffErASDSk=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":10.11,"multihop_port":25201}]},{"gateway":"no.wg.ivpn.net","country_code":"NO","country":"Norway","city":"Oslo","latitude":59.9167,"longitude":10.75,"isp":"Servetheworld","hosts":[{"hostname":"no1.wg.ivpn.net","host":"91.189.177.156","public_key":"xFO6ksbO3Gr05rRgAW0O5Veoi4bpTgz2G9RvtBzK7Cg=","local_ip":"172.16.0.1/12","ipv6":{},"load":0,"multihop_port":25301}]},{"gateway":"hu.wg.ivpn.net","country_code":"HU","country":"Hungary","city":"Budapest","latitude":47.5,"longitude":19.0833,"isp":"M247","hosts":[{"hostname":"hu1.wg.ivpn.net","host":"185.189.114.189","public_key":"G30fNdXrnlqtqqOLF23QXWzFdLIKDxLW60HoYPvqml8=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":100,"multihop_port":25401}]},{"gateway":"dk.wg.ivpn.net","country_code":"DK","country":"Denmark","city":"Copenhagen","latitude":55.6786,"longitude":12.5635,"isp":"M247","hosts":[{"hostname":"dk1.wg.ivpn.net","host":"185.245.84.229","public_key":"jTsV5gOD7lT4egDj9rhKwO2OO2X7bKs2EQPcZEnUWDE=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":74.13,"multihop_port":25501}]},{"gateway":"at.wg.ivpn.net","country_code":"AT","country":"Austria","city":"Vienna","latitude":48.2,"longitude":16.3666,"isp":"M247","hosts":[{"hostname":"at1.wg.ivpn.net","host":"185.244.212.69","public_key":"83LUBnP97SFpnS0y1MpEAFcg8MIiQJgW1FRv/8Mc40g=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":91.72,"multihop_port":25601}]},{"gateway":"be.wg.ivpn.net","country_code":"BE","country":"Belgium","city":"Brussels","latitude":50.8333,"longitude":4.3333,"isp":"M247","hosts":[{"hostname":"be1.wg.ivpn.net","host":"194.187.251.13","public_key":"awriP5lpdxEMWKuG+A1DOg+vb1M5jd3WhynIMB61BhU=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":60.31,"multihop_port":25701}]},{"gateway":"bg.wg.ivpn.net","country_code":"BG","country":"Bulgaria","city":"Sofia","latitude":42.6833,"longitude":23.3167,"isp":"M247","hosts":[{"hostname":"bg1.wg.ivpn.net","host":"82.102.23.21","public_key":"WDSsdJE6wvATIWfzQwayPtE/0DaXBQgW/hPm7sQSJmU=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":99.54,"multihop_port":25901}]},{"gateway":"sk.wg.ivpn.net","country_code":"SK","country":"Slovakia","city":"Bratislava","latitude":48.15,"longitude":17.117,"isp":"M247","hosts":[{"hostname":"sk1.wg.ivpn.net","host":"185.245.85.253","public_key":"MOBWWpEgNsKbFj4BEyWSDFLlkBs5iUFiqdSdTFTDBko=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":100,"multihop_port":25801}]},{"gateway":"jp.wg.ivpn.net","country_code":"JP","country":"Japan","city":"Tokyo","latitude":35.685,"longitude":139.7514,"isp":"M247","hosts":[{"hostname":"jp1.wg.ivpn.net","host":"91.207.174.237","public_key":"tb9WdC3LSho3d1rI5N7kfG9e42/d+u4LPVdEYERPsSQ=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":51.59,"multihop_port":26201},{"hostname":"jp2.wg.ivpn.net","host":"185.135.77.81","public_key":"YuhEd9+a90/+uucZC+qzsyMHkfe/GiwG1dq7g2HegXQ=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":9.97,"multihop_port":20830}]},{"gateway":"ua.wg.ivpn.net","country_code":"UA","country":"Ukraine","city":"Kharkiv","latitude":50,"longitude":36.25,"isp":"Xservers","hosts":[{"hostname":"ua1.wg.ivpn.net","host":"176.103.57.129","public_key":"mIxEzfjZ2wV6jJVj30w38ECd2LSH4bw/HLMnM2ICHiI=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":9.7,"multihop_port":26301}]},{"gateway":"fi.wg.ivpn.net","country_code":"FI","country":"Finland","city":"Helsinki","latitude":60.1756,"longitude":24.9341,"isp":"Creanova","hosts":[{"hostname":"fi1.wg.ivpn.net","host":"194.34.134.63","public_key":"mIxEzfjZ2wV6jJVj30w38ECd2LSH4bw/HLMnM2ICHiI=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":62.59,"multihop_port":26001}]},{"gateway":"us-az.wg.ivpn.net","country_code":"US","country":"United States","city":"Phoenix, AZ","latitude":33.5722,"longitude":-112.0891,"isp":"M247","hosts":[{"hostname":"us-az1.wg.ivpn.net","host":"193.37.254.133","public_key":"Ts4MGazxpxL9rrYbERjgxa+kCEX85ou9gHoaJvDsRiI=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":15.35,"multihop_port":26401}]},{"gateway":"us-nv.wg.ivpn.net","country_code":"US","country":"United States","city":"Las Vegas, NV","latitude":36.2333,"longitude":-115.2654,"isp":"M247","hosts":[{"hostname":"us-nv1.wg.ivpn.net","host":"185.242.5.37","public_key":"PRpvAZyoNWNm/KHlqafjtYoZtn1PkIPylUE4WbuYmgM=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":9.65,"multihop_port":26501}]},{"gateway":"au-nsw.wg.ivpn.net","country_code":"AU","country":"Australia","city":"Sydney","latitude":-33.92,"longitude":151.1852,"isp":"M247","hosts":[{"hostname":"au-nsw1.wg.ivpn.net","host":"46.102.153.246","public_key":"KmSrG48t5xw9CJCPlYLBG3JnmiY0CnUgyRM5TUEwZhM=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":80.52,"multihop_port":26601},{"hostname":"au-nsw2.wg.ivpn.net","host":"146.70.78.75","public_key":"q+wbp7GjiTszp5G16rNpGCqxkL0qSY3CH4pcgD6UsVQ=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":35.14,"multihop_port":27901}]},{"gateway":"br.wg.ivpn.net","country_code":"BR","country":"Brazil","city":"Franca","latitude":-20.53,"longitude":-47.39,"isp":"Qnax","hosts":[{"hostname":"br1.wg.ivpn.net","host":"45.162.229.133","public_key":"eN1f15S3YzRyYCALiPGRQcjkQO9xntcdqPhJJ6TOymc=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":44.16,"multihop_port":26701}]},{"gateway":"rs.wg.ivpn.net","country_code":"RS","country":"Serbia","city":"Belgrade","latitude":44.8186,"longitude":20.468,"isp":"M247","hosts":[{"hostname":"rs1.wg.ivpn.net","host":"141.98.103.253","public_key":"xLN/lpQThQ3z3tvYf7VqdAsRL/nton1Vhv2kCZlQtWE=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":31.33,"multihop_port":26801}]},{"gateway":"gb-man.wg.ivpn.net","country_code":"GB","country":"United Kingdom","city":"Manchester","latitude":53.5004,"longitude":-2.248,"isp":"M247","hosts":[{"hostname":"gb-man1.wg.ivpn.net","host":"89.238.141.231","public_key":"+hf4DYilNEIjTdSOuCNcWdqVyaRoxGzXw7wvNl7f7Rg=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":14.11,"multihop_port":26901}]},{"gateway":"pt.wg.ivpn.net","country_code":"PT","country":"Portugal","city":"Lisbon","latitude":38.7227,"longitude":-9.1449,"isp":"Hostwebis","hosts":[{"hostname":"pt1.wg.ivpn.net","host":"94.46.175.113","public_key":"nMnA82YVrvEK80GVoY/0Z9McWeqjcLzuMYSL+86j5nU=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":5.73,"multihop_port":27101}]},{"gateway":"lu.wg.ivpn.net","country_code":"LU","country":"Luxembourg","city":"Luxembourg","latitude":49.6117,"longitude":6.13,"isp":"Evoluso","hosts":[{"hostname":"lu1.wg.ivpn.net","host":"92.223.89.57","public_key":"hUS1OAFLGwpba8+oc5mifYtohZt/RTro5dMyYBLYHjI=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":90.71,"multihop_port":27201}]},{"gateway":"il.wg.ivpn.net","country_code":"IL","country":"Israel","city":"Holon, Tel Aviv","latitude":32.08,"longitude":34.77,"isp":"HQServ","hosts":[{"hostname":"il01.wg.ivpn.net","host":"185.191.207.197","public_key":"HR9gAjpxXU3YVt6kehBw5n8yVYVE0iIgJdc4HTqOzEE=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":37.73,"multihop_port":27301}]},{"gateway":"hk.wg.ivpn.net","country_code":"HK","country":"Hong Kong","city":"Hong Kong","latitude":22.305,"longitude":114.185,"isp":"Leaseweb","hosts":[{"hostname":"hk2.wg.ivpn.net","host":"64.120.120.239","public_key":"kyolyq4cJydI3vQB2ESTIUAy2Fq0bpOf+Qe7GIq6XEA=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":54.59,"multihop_port":27501},{"hostname":"hk3.wg.ivpn.net","host":"118.107.244.206","public_key":"qq1simsFNm2FpZM0J8u8Aa0rkk5HEasvLksPyLv+0Sk=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":8.91,"multihop_port":20800}]},{"gateway":"us-va.wg.ivpn.net","country_code":"US","country":"United States","city":"Ashburn, VA","latitude":39.0437,"longitude":-77.4875,"isp":"Datapacket","hosts":[{"hostname":"us-va1.wg.ivpn.net","host":"37.19.206.106","public_key":"ZCnZK6U+cRuP/WgzIDb/P6UG2rX/KyCRd5vJ1hAbr2E=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":53.2,"multihop_port":27701}]},{"gateway":"us-wa.wg.ivpn.net","country_code":"US","country":"United States","city":"Seattle, WA","latitude":47.6211,"longitude":-122.3244,"isp":"Tzulo","hosts":[{"hostname":"us-wa2.wg.ivpn.net","host":"198.44.131.4","public_key":"VcrOOozBUCIURU0AnqMAE7AkMmC7Qrp+j/PzPbgbalU=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":39.97,"multihop_port":27801}]},{"gateway":"tw.wg.ivpn.net","country_code":"TW","country":"Taiwan","city":"Taipei","latitude":25.073,"longitude":121.578,"isp":"TheGigabit","hosts":[{"hostname":"tw1.wg.ivpn.net","host":"185.189.160.59","public_key":"fMTCCbbKqPp60fkqnaQvJ9mX2r6zBlt7xhUp8sGfJQY=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":26.92,"multihop_port":20820}]},{"gateway":"my.wg.ivpn.net","country_code":"MY","country":"Malaysia","city":"Kuala Lumpur","latitude":3.1494,"longitude":101.706,"isp":"TheGigabit","hosts":[{"hostname":"my1.wg.ivpn.net","host":"61.4.97.153","public_key":"M9SsMCpUw7ad6YbqQr8r2saBK2zAf3tBj82DzsQjgkY=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":7.07,"multihop_port":20810}]},{"gateway":"za.wg.ivpn.net","country_code":"ZA","country":"South Africa","city":"Johannesburg","latitude":-26.195,"longitude":28.034,"isp":"Datapacket","hosts":[{"hostname":"za1.wg.ivpn.net","host":"169.150.238.108","public_key":"tgrAA+uJZppS9esgOi0pe3rHajQQ7c/KF8WPOua6qy4=","local_ip":"172.16.0.1/12","ipv6":{"local_ip":"fd00:4956:504e:ffff::/96"},"load":6.1,"multihop_port":20840}]}],"openvpn":[{"gateway":"us-ca.gw.ivpn.net","country_code":"US","country":"United States","city":"Los Angeles, CA","latitude":34.1139,"longitude":-118.4068,"isp":"Quadranet","hosts":[{"hostname":"us-ca1.gw.ivpn.net","host":"173.254.196.58","load":9.57,"multihop_port":22201,"obfs":{"obfs3_multihop_port":22202,"obfs4_multihop_port":22203,"obfs4_key":"C/Ct5AG8tkV0Yi7MnXv+bNvExY8Dgii4OeJ7DA7lIq3HptUa+WbG+IAR/UIDaMn8VeXDIg"}},{"hostname":"us-ca2.gw.ivpn.net","host":"69.12.80.146","load":7.08,"multihop_port":22401,"obfs":{"obfs3_multihop_port":22402,"obfs4_multihop_port":22403,"obfs4_key":"nvizO9jj1D3xMqCMTnP6XDIzTLy6KcYNsDSxvJjm5QwZ9Y+5gommAk9LIcCeX9o4FjlkVA"}},{"hostname":"us-ca3.gw.ivpn.net","host":"198.54.129.99","load":13.68,"multihop_port":21301,"obfs":{"obfs3_multihop_port":21302,"obfs4_multihop_port":21303,"obfs4_key":"rharPyhkUzYwmCP8ZzeaCwnJAmwOqwDTLOlJqzi/kAxMn4OVXtbzCk9Ww8XR31D2rmk3MA"}},{"hostname":"us-ca4.gw.ivpn.net","host":"173.254.204.202","load":7.21,"multihop_port":21901,"obfs":{"obfs3_multihop_port":21902,"obfs4_multihop_port":21903,"obfs4_key":"2Sdam2VI658TdQRvj5bxwKPFljrsKgwBDv/mqhXNYgDQGs+WVhAz508b2oWVgHed3Ki8dQ"}}]},{"gateway":"ro.gw.ivpn.net","country_code":"RO","country":"Romania","city":"Bucharest","latitude":44.4334,"longitude":26.0999,"isp":"M247","hosts":[{"hostname":"ro1.gw.ivpn.net","host":"37.120.206.50","load":47.19,"multihop_port":22301,"obfs":{"obfs3_multihop_port":22302,"obfs4_multihop_port":22303,"obfs4_key":"lqfg/sP9uLakoQiA6YI5/kHQ4/FvQTp6jRgxSswjHwC8POOM23FijEWKyykngn1Eb3xfLA"}}]},{"gateway":"de.gw.ivpn.net","country_code":"DE","country":"Germany","city":"Frankfurt","latitude":50.1,"longitude":8.675,"isp":"Leaseweb","hosts":[{"hostname":"de1.gw.ivpn.net","host":"178.162.222.40","load":25.53,"multihop_port":23001,"obfs":{"obfs3_multihop_port":23002,"obfs4_multihop_port":23003,"obfs4_key":"PBhcWVcRNOCTMSWXbA2J+8eJBVzNd9H5HOr0YCF8QWwmKeSlEmqLSJQE8oDpKH5IbFH4Mw"}},{"hostname":"de2.gw.ivpn.net","host":"178.162.211.114","load":9.54,"multihop_port":22001,"obfs":{"obfs3_multihop_port":22002,"obfs4_multihop_port":22003,"obfs4_key":"dEhLA4ZsvVP8+PRvlSHKwmW8JyzR1Bwy7+BFKF7Ux4L2B5YvdqqOrv/8eHliEj2mm2Z8Iw"}}]},{"gateway":"nl.gw.ivpn.net","country_code":"NL","country":"Netherlands","city":"Amsterdam","latitude":52.35,"longitude":4.9166,"isp":"Leaseweb","hosts":[{"hostname":"nl4.gw.ivpn.net","host":"95.211.172.95","load":15.89,"multihop_port":23201,"obfs":{"obfs3_multihop_port":23202,"obfs4_multihop_port":23203,"obfs4_key":"KEw6WJF+NDOQv7yMvq+dAAAkPbcYJ8PX6pffRd8EM3uaOy2QcpMcdHI7s700Kq/ZvV3HBQ"}},{"hostname":"nl3.gw.ivpn.net","host":"95.211.172.68","load":6.67,"multihop_port":23101,"obfs":{"obfs3_multihop_port":23102,"obfs4_multihop_port":23103,"obfs4_key":"eUXsScIg0K0LKVgA8yq2Mc++pfnTQ9nr3gnV8n1NIw7wRqinhO6uuXiSS5J19agQaPK1ew"}},{"hostname":"nl6.gw.ivpn.net","host":"95.211.187.228","load":20.91,"multihop_port":24101,"obfs":{"obfs3_multihop_port":24102,"obfs4_multihop_port":24103,"obfs4_key":"lT3OGPQS1CwwqtalMExN7qxEoDDBLLlcoh5a6YW3DPj8esEBEG6wY5OfYonxltBzoVu4PA"}},{"hostname":"nl5.gw.ivpn.net","host":"95.211.187.222","load":40.56,"multihop_port":23901,"obfs":{"obfs3_multihop_port":23902,"obfs4_multihop_port":23903,"obfs4_key":"fcWCrzzatLbk1LNKsuQZKpQrC3ZXwQ85GO5xRS467KJBRDrmvnyMb6ARbLGu+gYkTnNELQ"}},{"hostname":"nl7.gw.ivpn.net","host":"95.211.95.22","load":8.57,"multihop_port":22501,"obfs":{"obfs3_multihop_port":22502,"obfs4_multihop_port":22503,"obfs4_key":"ffMnq7Gc/D7KWoLckJ4t8nf3zZqVdlffe2lVfUCceOyOTdRApkeJGgEai0TI1z76Yey9Lw"}},{"hostname":"nl8.gw.ivpn.net","host":"95.211.172.18","load":21.1,"multihop_port":22801,"obfs":{"obfs3_multihop_port":22802,"obfs4_multihop_port":22803,"obfs4_key":"h+u/6VkPDJXySoJ6QEM1hOjWPD58OS4AZPP9ofP/yCWGBQpPoMc78l7C74eFvqKKkFAXDw"}}]},{"gateway":"fr.gw.ivpn.net","country_code":"FR","country":"France","city":"Paris","latitude":48.8667,"longitude":2.3333,"isp":"Datapacket","hosts":[{"hostname":"fr1.gw.ivpn.net","host":"185.246.211.179","load":32.72,"multihop_port":23401,"obfs":{"obfs3_multihop_port":23402,"obfs4_multihop_port":23403,"obfs4_key":"CMf0pNZ46nFdG0Tpa3hE0cK9wtUAReJL7HN66G9Jq3tlrTSWrU0DLf7sCQgXV+WFoc8iaw"}}]},{"gateway":"is.gw.ivpn.net","country_code":"IS","country":"Iceland","city":"Reykjavik","latitude":64.15,"longitude":-21.95,"isp":"Advania","hosts":[{"hostname":"is1.gw.ivpn.net","host":"82.221.107.178","load":59.02,"multihop_port":23501,"obfs":{"obfs3_multihop_port":23502,"obfs4_multihop_port":23503,"obfs4_key":"xx/Lor3q60/pVh4PKWi0GZaw64pPXFTkALnGlvRaBMiPRkFilr7KhYmPInDnZxzr4c4AIw"}}]},{"gateway":"us-tx.gw.ivpn.net","country_code":"US","country":"United States","city":"Dallas, TX","latitude":32.7936,"longitude":-96.7662,"isp":"Quadranet","hosts":[{"hostname":"us-tx1.gw.ivpn.net","host":"96.44.189.194","load":15.49,"multihop_port":21001,"obfs":{"obfs3_multihop_port":21002,"obfs4_multihop_port":21003,"obfs4_key":"GBDWrGN71fGa7a7S8b2tHzjYQMhnA2vJW5yq3iID+VoSzA1xIAgHiOxISEU93v+CBTCXWg"}},{"hostname":"us-tx2.gw.ivpn.net","host":"96.44.142.74","load":9.84,"multihop_port":25001,"obfs":{"obfs3_multihop_port":25002,"obfs4_multihop_port":25003,"obfs4_key":"VYfEVELWNqOm7kyO19usXm3GSK9wawRObopQLOLDbLodKnmX/jPah+IlGkL2xYiNxEzUKw"}}]},{"gateway":"gb.gw.ivpn.net","country_code":"GB","country":"United Kingdom","city":"London","latitude":51.5,"longitude":-0.1167,"isp":"Datapacket","hosts":[{"hostname":"gb2.gw.ivpn.net","host":"185.59.221.88","load":7.16,"multihop_port":24201,"obfs":{"obfs3_multihop_port":24202,"obfs4_multihop_port":24203,"obfs4_key":"4hrCOgPsRfmnQ6cLvV5mtM2XZCRS/DXG/izYSg2qZC+WJ0GsnhTlKByPM2iJ555MaM8vJA"}},{"hostname":"gb1.gw.ivpn.net","host":"185.59.221.133","load":22.87,"multihop_port":20801,"obfs":{"obfs3_multihop_port":20802,"obfs4_multihop_port":20803,"obfs4_key":"5whTESvZxQE28wKqJWZ9fQFy09d8//GNaPDeYHVR+FJZTyI+DMS6qX4Mt2FKSf/zBToaDg"}}]},{"gateway":"us-ut.gw.ivpn.net","country_code":"US","country":"United States","city":"Salt Lake City, UT","latitude":40.7774,"longitude":-111.93,"isp":"100TB","hosts":[{"hostname":"us-ut1.gw.ivpn.net","host":"198.105.216.28","load":17.04,"multihop_port":24401,"obfs":{"obfs3_multihop_port":24402,"obfs4_multihop_port":24403,"obfs4_key":"gb5dp9i4QnFKT0GQPMEsDlqN+JORU3lyU65s9R1064aZ1jKfWfkc+SxbOlNEh23CvIAOeg"}}]},{"gateway":"it.gw.ivpn.net","country_code":"IT","country":"Italy","city":"Milan","latitude":45.47,"longitude":9.205,"isp":"SEFlow","hosts":[{"hostname":"it1.gw.ivpn.net","host":"158.58.172.73","load":12.37,"multihop_port":24301,"obfs":{"obfs3_multihop_port":24302,"obfs4_multihop_port":24303,"obfs4_key":"yJXSlTJloo6tlAxf0MI9Bu4schtcL2NlVqMPgbrhnrT/1pTZUaOUH7F7nLbVe4JSCSyeZg"}}]},{"gateway":"se.gw.ivpn.net","country_code":"SE","country":"Sweden","city":"Stockholm","latitude":59.3508,"longitude":18.0973,"isp":"GleSyS","hosts":[{"hostname":"se1.gw.ivpn.net","host":"80.67.10.138","load":5.52,"multihop_port":24001,"obfs":{"obfs3_multihop_port":24002,"obfs4_multihop_port":24003,"obfs4_key":"/yhTV2SsTXlwsG2mCS90ZAYIZivsSyloaFw6VDj0pnpJOuUxXcZBOgdyQ/lfWxJtvHZmPg"}}]},{"gateway":"us-ga.gw.ivpn.net","country_code":"US","country":"United States","city":"Atlanta, GA","latitude":33.7627,"longitude":-84.4225,"isp":"Quadranet","hosts":[{"hostname":"us-ga1.gw.ivpn.net","host":"104.129.24.146","load":30.84,"multihop_port":24501,"obfs":{"obfs3_multihop_port":24502,"obfs4_multihop_port":24503,"obfs4_key":"+No53UtdyPN4uT89vMlvRTjFnxtMKol+oOld9I9WMnlK7BU+y10oXWofzcI4eRgkm195FQ"}},{"hostname":"us-ga2.gw.ivpn.net","host":"107.150.22.74","load":8.51,"multihop_port":24810,"obfs":{"obfs3_multihop_port":24811,"obfs4_multihop_port":24812,"obfs4_key":"3viWXkxZx1KZF9uzd5tRxb5lNMMnRZ90PqwLUaZdkZuaouj+Vb20t5uk3BVz/YyZkrSoGw"}}]},{"gateway":"us-fl.gw.ivpn.net","country_code":"US","country":"United States","city":"Miami, FL","latitude":25.7839,"longitude":-80.2102,"isp":"Quadranet","hosts":[{"hostname":"us-fl1.gw.ivpn.net","host":"173.44.49.90","load":13.74,"multihop_port":24601,"obfs":{"obfs3_multihop_port":24602,"obfs4_multihop_port":24603,"obfs4_key":"vS7u4rijvWECRS/Mo2KOpl8kx0NOozp3kF/FMxGmCZILE46etitrheYI2hCpNsYUg3YTBQ"}}]},{"gateway":"ca.gw.ivpn.net","country_code":"CA","country":"Canada","city":"Toronto","latitude":43.7,"longitude":-79.42,"isp":"Amanah","hosts":[{"hostname":"ca2.gw.ivpn.net","host":"172.86.186.170","load":100,"multihop_port":22101,"obfs":{"obfs3_multihop_port":22102,"obfs4_multihop_port":22103,"obfs4_key":"xNkQbCkA0VCe2i4WvS2CPq2eBSMydIjsHH36E+Yg0C+gOPo3SwZyN51kpB+kwsYVS32fOQ"}},{"hostname":"ca1.gw.ivpn.net","host":"104.254.90.178","load":82.06,"multihop_port":23801,"obfs":{"obfs3_multihop_port":23802,"obfs4_multihop_port":23803,"obfs4_key":"49WDCCK1QGpOTSEVflRzIIaOdCT1BLB3jr/yNUJsbaUFrq7NuoB1E3wAdArNxQq9p5otTw"}}]},{"gateway":"ch.gw.ivpn.net","country_code":"CH","country":"Switzerland","city":"Zurich","latitude":47.38,"longitude":8.55,"isp":"Privatelayer","hosts":[{"hostname":"ch3.gw.ivpn.net","host":"141.255.166.194","load":20.08,"multihop_port":22901,"obfs":{"obfs3_multihop_port":22902,"obfs4_multihop_port":22903,"obfs4_key":"oNaH5sHCPGGk5m3/VMOrTDL+m1qsJrze+bqDs78vhOYBpjx5Jjq5TXu1dXNfDJCKNmKnUA"}},{"hostname":"ch1.gw.ivpn.net","host":"185.212.170.138","load":54.97,"multihop_port":23601,"obfs":{"obfs3_multihop_port":23602,"obfs4_multihop_port":23603,"obfs4_key":"ELnV4JNKu0vUNd3J+QDn64yfZtqM0hNN6O5n6RkDLHbeSDBZmxP1N4dlwwChV/uySX+DEQ"}}]},{"gateway":"us-il.gw.ivpn.net","country_code":"US","country":"United States","city":"Chicago, IL","latitude":41.8373,"longitude":-87.6862,"isp":"Quadranet","hosts":[{"hostname":"us-il1.gw.ivpn.net","host":"107.150.28.82","load":14.63,"multihop_port":21401,"obfs":{"obfs3_multihop_port":21402,"obfs4_multihop_port":21403,"obfs4_key":"6PpxOt8CwINAjun8o/wsf/cAidNbJZM/Pg4im1Cx9kCBV/lau3XFq3bMwBW0SzptZ/5WdA"}},{"hostname":"us-il2.gw.ivpn.net","host":"72.11.137.146","load":11.84,"multihop_port":24901,"obfs":{"obfs3_multihop_port":24902,"obfs4_multihop_port":24903,"obfs4_key":"cfvJR/gplqAbFx8myJSW/cPC3hN1782PPma2v5YKJR5LyekWX+AHTJjzdz8xSr2mM6IGQw"}}]},{"gateway":"us-nj.gw.ivpn.net","country_code":"US","country":"United States","city":"New Jersey, NJ","latitude":40.737764,"longitude":-74.151747,"isp":"Quadranet","hosts":[{"hostname":"us-nj3.gw.ivpn.net","host":"23.226.128.18","load":29.57,"multihop_port":21610,"obfs":{"obfs3_multihop_port":21611,"obfs4_multihop_port":21612,"obfs4_key":"JtB/8Lv8MOq9+bpYC751voS2CwoEwf9ku2CziwJScn3Gc1F/BTul6ehnrGiedmpkQXAtJw"}},{"hostname":"us-nj4.gw.ivpn.net","host":"194.36.111.50","load":7.71,"multihop_port":27401,"obfs":{"obfs3_multihop_port":27402,"obfs4_multihop_port":27403,"obfs4_key":"lHDLT6cTgt0bh3ysogDdiXL4eWGRtJZ0cZGJmvpeK0YLUAsBfsOzKv46V0iv5ykwRPm6Mg"}}]},{"gateway":"es.gw.ivpn.net","country_code":"ES","country":"Spain","city":"Madrid","latitude":40.4,"longitude":-3.6834,"isp":"Datapacket","hosts":[{"hostname":"es1.gw.ivpn.net","host":"185.93.3.193","load":15.04,"multihop_port":21501,"obfs":{"obfs3_multihop_port":21502,"obfs4_multihop_port":21503,"obfs4_key":"x4A9SBY5yzPKH1QOkEsGYcIR2JA/Pu393jv/ZSg4YO2DsVhr3TQFxcMO3QhD9iSF48smJA"}}]},{"gateway":"us-ny.gw.ivpn.net","country_code":"US","country":"United States","city":"New York, NY","latitude":40.6943,"longitude":-73.9249,"isp":"M247","hosts":[{"hostname":"us-ny2.gw.ivpn.net","host":"212.103.48.194","load":5.1,"multihop_port":21801,"obfs":{"obfs3_multihop_port":21802,"obfs4_multihop_port":21803,"obfs4_key":"GtK9yCXTtrLOrf0MTWdWqjzQ1vd1eKsVjiOuR5CiVaDf4dCSalyJ+kmik4nfU9Gj6UwcCg"}},{"hostname":"us-ny3.gw.ivpn.net","host":"89.187.178.144","load":8.51,"multihop_port":27601,"obfs":{"obfs3_multihop_port":27602,"obfs4_multihop_port":27603,"obfs4_key":"eL/9iKx6f5bHowNJBsT2E/Aag5w8Cvtb3DduySudJmuK2GtIOUwNzS33lFZwSUEnJIYwLg"}}]},{"gateway":"pl.gw.ivpn.net","country_code":"PL","country":"Poland","city":"Warsaw","latitude":52.25,"longitude":21,"isp":"Datapacket","hosts":[{"hostname":"pl1.gw.ivpn.net","host":"185.246.208.86","load":16.52,"multihop_port":25101,"obfs":{"obfs3_multihop_port":25102,"obfs4_multihop_port":25103,"obfs4_key":"S9XZyigxYjF5jWcwYpMmV9HJq4Vni1yQvLKI03n0TJ7csrgsX7lPpFfECAGQruHh1wkMXg"}}]},{"gateway":"cz.gw.ivpn.net","country_code":"CZ","country":"Czech Republic","city":"Prague","latitude":50.0833,"longitude":14.466,"isp":"Datapacket","hosts":[{"hostname":"cz1.gw.ivpn.net","host":"195.181.160.167","load":10.11,"multihop_port":25201,"obfs":{"obfs3_multihop_port":25202,"obfs4_multihop_port":25203,"obfs4_key":"JZ3PtIyflM3VwVow2vqi08OxddOWSx9j6B6yZSGoZLs9QE0hzSAj3ZBWEsCKFeQ2RcAoCQ"}}]},{"gateway":"no.gw.ivpn.net","country_code":"NO","country":"Norway","city":"Oslo","latitude":59.9167,"longitude":10.75,"isp":"Servetheworld","hosts":[{"hostname":"no1.gw.ivpn.net","host":"194.242.10.150","load":12.19,"multihop_port":25301,"obfs":{"obfs3_multihop_port":25302,"obfs4_multihop_port":25303,"obfs4_key":"uhLy//KRu6DrYfgDJmwjC6Fxk5h+MRDNOwFe7qzGTjfOiHLWRSoRx6OdNvzjPPXq0ZJnZg"}}]},{"gateway":"hu.gw.ivpn.net","country_code":"HU","country":"Hungary","city":"Budapest","latitude":47.5,"longitude":19.0833,"isp":"M247","hosts":[{"hostname":"hu1.gw.ivpn.net","host":"185.189.114.186","load":100,"multihop_port":25401,"obfs":{"obfs3_multihop_port":25402,"obfs4_multihop_port":25403,"obfs4_key":"2TwZqxAakni0S4S3ulOIqMZimqqug0KCr6pNREN6KytrtIh486nkJyiFRqaYZlx+FlxEcg"}}]},{"gateway":"dk.gw.ivpn.net","country_code":"DK","country":"Denmark","city":"Copenhagen","latitude":55.6786,"longitude":12.5635,"isp":"M247","hosts":[{"hostname":"dk1.gw.ivpn.net","host":"185.245.84.226","load":74.13,"multihop_port":25501,"obfs":{"obfs3_multihop_port":25502,"obfs4_multihop_port":25503,"obfs4_key":"ngjtv9UISX4tB5AkBnrEN2TrAnUqVwNZ688VqDlS4BDxQXJeJF3ynZtngRqeowhEahsccQ"}}]},{"gateway":"at.gw.ivpn.net","country_code":"AT","country":"Austria","city":"Vienna","latitude":48.2,"longitude":16.3666,"isp":"M247","hosts":[{"hostname":"at1.gw.ivpn.net","host":"185.244.212.66","load":91.72,"multihop_port":25601,"obfs":{"obfs3_multihop_port":25602,"obfs4_multihop_port":25603,"obfs4_key":"75HhQC6n6ctp9Fa9wCvEnc6ip5FnEfuIGc+dVNLH4M15FjB/Ve6bI1b8lYFhk6T+4/HkDQ"}}]},{"gateway":"be.gw.ivpn.net","country_code":"BE","country":"Belgium","city":"Brussels","latitude":50.8333,"longitude":4.3333,"isp":"M247","hosts":[{"hostname":"be1.gw.ivpn.net","host":"194.187.251.10","load":60.31,"multihop_port":25701,"obfs":{"obfs3_multihop_port":25702,"obfs4_multihop_port":25703,"obfs4_key":"cN8i60FUVy2mmGpy+tkQAz8hu/N0EGPq8cZwIotEDwdhAYdLV+ATes/AEjzdub2K68TlYg"}}]},{"gateway":"bg.gw.ivpn.net","country_code":"BG","country":"Bulgaria","city":"Sofia","latitude":42.6833,"longitude":23.3167,"isp":"M247","hosts":[{"hostname":"bg1.gw.ivpn.net","host":"82.102.23.18","load":99.54,"multihop_port":25901,"obfs":{"obfs3_multihop_port":25902,"obfs4_multihop_port":25903,"obfs4_key":"K+mCw9+zy/8pBQt6IUKRlg2eJ3DCnJ1BvIccLq/6A2D6HoZddyDnZQYb2Sb2e464dVgBWw"}}]},{"gateway":"sk.gw.ivpn.net","country_code":"SK","country":"Slovakia","city":"Bratislava","latitude":48.15,"longitude":17.117,"isp":"M247","hosts":[{"hostname":"sk1.gw.ivpn.net","host":"185.245.85.250","load":100,"multihop_port":25801,"obfs":{"obfs3_multihop_port":25802,"obfs4_multihop_port":25803,"obfs4_key":"8sl7oPfNHdCd2xYi98xWC6mBXyPvzio34UbfUbCPEU+8wo7DVbrR9mf8goR0Ievqzax4Hw"}}]},{"gateway":"jp.gw.ivpn.net","country_code":"JP","country":"Japan","city":"Tokyo","latitude":35.685,"longitude":139.7514,"isp":"M247","hosts":[{"hostname":"jp1.gw.ivpn.net","host":"91.207.174.234","load":51.59,"multihop_port":26201,"obfs":{"obfs3_multihop_port":26202,"obfs4_multihop_port":26203,"obfs4_key":"CBqi0EpfoUzP/ijwYn9A9yEpItrhtX+BAKF0rvcUGv///UNzzXKNz+0RhBLdQayZx6y6TA"}},{"hostname":"jp2.gw.ivpn.net","host":"185.135.77.35","load":9.97,"multihop_port":20830,"obfs":{"obfs3_multihop_port":20831,"obfs4_multihop_port":20832,"obfs4_key":"giZJF4edg7wcjxbdgD2RjFcF9QAzExLHIJYjm2cLLtx7MrxP0p96mIFj9T8LSQotKB63fA"}}]},{"gateway":"sg.gw.ivpn.net","country_code":"SG","country":"Singapore","city":"Singapore","latitude":1.293,"longitude":103.8558,"isp":"M247","hosts":[{"hostname":"sg1.gw.ivpn.net","host":"185.128.24.186","load":53.29,"multihop_port":26101,"obfs":{"obfs3_multihop_port":26102,"obfs4_multihop_port":26103,"obfs4_key":"0N1ZmZlnyhS/3Y1OhvB0Bk3BGU2LFy0zyuWPYwM/P+mfX57w8zI7/YcBfIXZVgDiStt4MQ"}}]},{"gateway":"ua.gw.ivpn.net","country_code":"UA","country":"Ukraine","city":"Kharkiv","latitude":50,"longitude":36.25,"isp":"Xservers","hosts":[{"hostname":"ua1.gw.ivpn.net","host":"176.103.58.123","load":9.7,"multihop_port":26301,"obfs":{"obfs3_multihop_port":26302,"obfs4_multihop_port":26303,"obfs4_key":"RsW3q+FmLATkKnKHOheUntwvslkrXEiCBx3ajDjhyHiZMtQI+Uy7TmhFK0YaHg/qKoljYw"}}]},{"gateway":"fi.gw.ivpn.net","country_code":"FI","country":"Finland","city":"Helsinki","latitude":60.1756,"longitude":24.9341,"isp":"Creanova","hosts":[{"hostname":"fi1.gw.ivpn.net","host":"185.112.82.12","load":62.59,"multihop_port":26001,"obfs":{"obfs3_multihop_port":26002,"obfs4_multihop_port":26003,"obfs4_key":"SvvSpGiFctjs4n2wZGnZUf9fAL8wag70SrA3FX+9f3Sq+KgBn+/8P6fE3239ezemg9svLA"}}]},{"gateway":"us-az.gw.ivpn.net","country_code":"US","country":"United States","city":"Phoenix, AZ","latitude":33.5722,"longitude":-112.0891,"isp":"M247","hosts":[{"hostname":"us-az1.gw.ivpn.net","host":"193.37.254.130","load":15.35,"multihop_port":26401,"obfs":{"obfs3_multihop_port":26402,"obfs4_multihop_port":26403,"obfs4_key":"Y2klMvUi3NBIReXSALaKnNm8qI9IdWhFwgQrwl9ofUuVNuT6D93ohTTqbW//iKS5/lqndw"}}]},{"gateway":"us-nv.gw.ivpn.net","country_code":"US","country":"United States","city":"Las Vegas, NV","latitude":36.2333,"longitude":-115.2654,"isp":"M247","hosts":[{"hostname":"us-nv1.gw.ivpn.net","host":"185.242.5.34","load":9.65,"multihop_port":26501,"obfs":{"obfs3_multihop_port":26502,"obfs4_multihop_port":26503,"obfs4_key":"Kux7OTSrUOkklATpG67hJPz7xCWpW6eD9Qdw2GNKAmaaPA5zvPC3SXQRvyrYdyAAqMXMfg"}}]},{"gateway":"au-nsw.gw.ivpn.net","country_code":"AU","country":"Australia","city":"Sydney","latitude":-33.92,"longitude":151.1852,"isp":"M247","hosts":[{"hostname":"au-nsw1.gw.ivpn.net","host":"46.102.153.242","load":80.52,"multihop_port":26601,"obfs":{"obfs3_multihop_port":26602,"obfs4_multihop_port":26603,"obfs4_key":"/rjoeDjduOFq1UvT332vhS398h1RP5hC3m7sDJKNSyJ6TO8mkcxWAYILw0i+bgS/3JD5YA"}},{"hostname":"au-nsw2.gw.ivpn.net","host":"146.70.78.74","load":35.14,"multihop_port":27901,"obfs":{"obfs3_multihop_port":27902,"obfs4_multihop_port":27903,"obfs4_key":"qtdQ5krD9EQFR98xNo/v5cmGb10wqt0Om9pYMIHWQh4oz5xcAXj32rViEyN0bnkkhaZnBA"}}]},{"gateway":"br.gw.ivpn.net","country_code":"BR","country":"Brazil","city":"Franca","latitude":-20.53,"longitude":-47.39,"isp":"Qnax","hosts":[{"hostname":"br1.gw.ivpn.net","host":"45.162.229.130","load":44.16,"multihop_port":26701,"obfs":{"obfs3_multihop_port":26702,"obfs4_multihop_port":26703,"obfs4_key":"h4bBkocahWveuv/nWPRMYXBTw95ExTiXwmoydkNlV6hgfy8/ZjaKc34rqTuOyOH+CK7OZw"}}]},{"gateway":"rs.gw.ivpn.net","country_code":"RS","country":"Serbia","city":"Belgrade","latitude":44.8186,"longitude":20.468,"isp":"M247","hosts":[{"hostname":"rs1.gw.ivpn.net","host":"141.98.103.250","load":31.33,"multihop_port":26801,"obfs":{"obfs3_multihop_port":26802,"obfs4_multihop_port":26803,"obfs4_key":"0MqgxLrLFQTlQWGAjY9es+Nv45d37/5lulWw0iEFoiUvtzOcbut8hK9AhCis17EXi+lUXw"}}]},{"gateway":"gb-man.gw.ivpn.net","country_code":"GB","country":"United Kingdom","city":"Manchester","latitude":53.5004,"longitude":-2.248,"isp":"M247","hosts":[{"hostname":"gb-man1.gw.ivpn.net","host":"89.238.141.228","load":14.11,"multihop_port":26901,"obfs":{"obfs3_multihop_port":26902,"obfs4_multihop_port":26903,"obfs4_key":"WuP3pMrsQA+uAC72sV+Y62E1uvOWcnbTNJCmRHXqtWbbYzECF5swu62dzD/JOKoa5t0tGQ"}}]},{"gateway":"ca-qc.gw.ivpn.net","country_code":"CA","country":"Canada","city":"Montreal","latitude":45.5,"longitude":-73.5833,"isp":"M247","hosts":[{"hostname":"ca-qc1.gw.ivpn.net","host":"87.101.92.26","load":50.12,"multihop_port":27001,"obfs":{"obfs3_multihop_port":27002,"obfs4_multihop_port":27003,"obfs4_key":"E97qdaar8flBavysmvdIui7WQEFKkbmNi/ITTo8bPLvv39vnaBRzFj4vjMwpzXV2jXEGRQ"}}]},{"gateway":"pt.gw.ivpn.net","country_code":"PT","country":"Portugal","city":"Lisbon","latitude":38.7227,"longitude":-9.1449,"isp":"Hostwebis","hosts":[{"hostname":"pt1.gw.ivpn.net","host":"94.46.175.112","load":5.73,"multihop_port":27101,"obfs":{"obfs3_multihop_port":27102,"obfs4_multihop_port":27103,"obfs4_key":"NqXqKMt8UF25hYDIwfh2K4Rr4a7F41HzZDGjX7SYwRaoOtrTL665yV6Z3h9wF+/R1YE8KQ"}}]},{"gateway":"lu.gw.ivpn.net","country_code":"LU","country":"Luxembourg","city":"Luxembourg","latitude":49.6117,"longitude":6.13,"isp":"Evoluso","hosts":[{"hostname":"lu1.gw.ivpn.net","host":"92.223.89.53","load":90.71,"multihop_port":27201,"obfs":{"obfs3_multihop_port":27202,"obfs4_multihop_port":27203,"obfs4_key":"auDmK8lVBI7fxq6UjXg7V0qoZJ3icACKm/9vruMGSr0lT6ViNsl28qMqYbjJRveHnx5eQw"}}]},{"gateway":"il.gw.ivpn.net","country_code":"IL","country":"Israel","city":"Holon, Tel Aviv","latitude":32.08,"longitude":34.77,"isp":"HQServ","hosts":[{"hostname":"il1.gw.ivpn.net","host":"185.191.207.194","load":37.73,"multihop_port":27301,"obfs":{"obfs3_multihop_port":27302,"obfs4_multihop_port":27303,"obfs4_key":"DysuSM7UWjquj4BAVYf6mOUnRKfY1QXs17MXiV5aYapFfOkQPpx5nQPVQ2M+rLDxN9TSRg"}}]},{"gateway":"hk.gw.ivpn.net","country_code":"HK","country":"Hong Kong","city":"Hong Kong","latitude":22.305,"longitude":114.185,"isp":"Leaseweb","hosts":[{"hostname":"hk2.gw.ivpn.net","host":"209.58.188.13","load":54.59,"multihop_port":27501,"obfs":{"obfs3_multihop_port":27502,"obfs4_multihop_port":27503,"obfs4_key":"GIunWjiq00Piv3Xf4VeMkmUQ8NzD8sxRkSIbA3bxrU4LhPVth+3qM2zQwI4GesQDCDY5RA"}},{"hostname":"hk3.gw.ivpn.net","host":"118.107.244.184","load":8.91,"multihop_port":20800,"obfs":{"obfs3_multihop_port":20801,"obfs4_multihop_port":20802,"obfs4_key":"wnI0gz3hLM9VhkABSncBIsGERgn16UzTxkj7dEeYYo/y2Wu0/w24rfriA5KL7ugpTyvEFg"}}]},{"gateway":"us-va.gw.ivpn.net","country_code":"US","country":"United States","city":"Ashburn, VA","latitude":39.0437,"longitude":-77.4875,"isp":"Datapacket","hosts":[{"hostname":"us-va1.gw.ivpn.net","host":"37.19.206.105","load":53.2,"multihop_port":27701,"obfs":{"obfs3_multihop_port":27702,"obfs4_multihop_port":27703,"obfs4_key":"5Lk8BSID+M9QAGSglQTrYkom+V0mkIv0HgR80+9vKCcnZOu0f+aJhfOXqKnpHarJbIEHCw"}}]},{"gateway":"us-wa.gw.ivpn.net","country_code":"US","country":"United States","city":"Seattle, WA","latitude":47.6211,"longitude":-122.3244,"isp":"Tzulo","hosts":[{"hostname":"us-wa2.gw.ivpn.net","host":"198.44.131.3","load":39.97,"multihop_port":27801,"obfs":{"obfs3_multihop_port":27802,"obfs4_multihop_port":27803,"obfs4_key":"9h0W5BTzGSDpY2tGjdvViSJfEkT/BuwHS0cnFX07cEj3RRDtmxsC0f+kapO8+Kh+fz1XMQ"}}]},{"gateway":"tw.gw.ivpn.net","country_code":"TW","country":"Taiwan","city":"Taipei","latitude":25.073,"longitude":121.578,"isp":"TheGigabit","hosts":[{"hostname":"tw1.gw.ivpn.net","host":"185.189.160.6","load":26.92,"multihop_port":20820,"obfs":{"obfs3_multihop_port":20821,"obfs4_multihop_port":20822,"obfs4_key":"/ilRlB3BkUzUG2yd+++6KeYEF9PEB+3T3XcQhVjfoF8wJH1kgjGXvikjS1j/1SknFpGPaA"}}]},{"gateway":"my.gw.ivpn.net","country_code":"MY","country":"Malaysia","city":"Kuala Lumpur","latitude":3.1494,"longitude":101.706,"isp":"TheGigabit","hosts":[{"hostname":"my1.gw.ivpn.net","host":"61.4.97.148","load":7.07,"multihop_port":20810,"obfs":{"obfs3_multihop_port":20811,"obfs4_multihop_port":20812,"obfs4_key":"k2hwCe8gDb24K5n2jNXYO5YCl5XCIEhuRwpYSsEhKWorah8OUM1C1crawbfstj+W2IQdOA"}}]},{"gateway":"za.gw.ivpn.net","country_code":"ZA","country":"South Africa","city":"Johannesburg","latitude":-26.195,"longitude":28.034,"isp":"Datapacket","hosts":[{"hostname":"za1.gw.ivpn.net","host":"169.150.238.103","load":6.1,"multihop_port":20840,"obfs":{"obfs3_multihop_port":20841,"obfs4_multihop_port":20842,"obfs4_key":"vM1zdiOMhoqMKZCOi/lMj7TfWJb5/UsM25p8FE/AUezwbYWhUkhpD5RbXBOBDNhZuYzPGA"}}]}],"config":{"antitracker":{"default":{"ip":"10.0.254.2","multihop-ip":"10.0.254.102"},"hardcore":{"ip":"10.0.254.3","multihop-ip":"10.0.254.103"}},"api":{"ips":["198.50.177.220","149.56.162.156","198.50.177.222","149.56.162.159","198.50.177.223"],"ipv6s":["2607:5300:203:1735::8888","2607:5300:203:1735::8","2607:5300:203:1735:6580:7300:0:aaaa"]},"ports":{"openvpn":[{"type":"UDP","port":53},{"type":"UDP","port":80},{"type":"UDP","range":{"min":5500,"max":19999}},{"type":"UDP","range":{"min":60000,"max":65000}},{"type":"UDP","port":123},{"type":"UDP","port":2049},{"type":"UDP","range":{"min":50000,"max":59999}},{"type":"UDP","port":2050},{"type":"UDP","range":{"min":40000,"max":49999}},{"type":"UDP","port":443},{"type":"UDP","port":1194},{"type":"UDP","range":{"min":30000,"max":39999}},{"type":"TCP","port":80},{"type":"TCP","port":443},{"type":"TCP","port":1194},{"type":"TCP","port":2049},{"type":"TCP","port":2050},{"type":"TCP","port":30587},{"type":"TCP","port":41893},{"type":"TCP","port":48574},{"type":"TCP","port":58237},{"type":"TCP","range":{"min":5500,"max":19999}},{"type":"TCP","range":{"min":30000,"max":65000}}],"wireguard":[{"type":"UDP","port":53},{"type":"UDP","port":80},{"type":"UDP","port":123},{"type":"UDP","port":443},{"type":"UDP","port":500},{"type":"UDP","port":1194},{"type":"UDP","port":2049},{"type":"UDP","port":2050},{"type":"UDP","port":4500},{"type":"UDP","port":30587},{"type":"UDP","port":41893},{"type":"UDP","port":48574},{"type":"UDP","port":58237},{"type":"UDP","range":{"min":5500,"max":19999}},{"type":"UDP","range":{"min":30000,"max":65000}}],"obfs3":{"port":5145},"obfs4":{"port":5146}}}}
diff --git a/IVPNClient/Enums/ConnectionSettings.swift b/IVPNClient/Enums/ConnectionSettings.swift
index 401f7b7a7..41c8d89dc 100644
--- a/IVPNClient/Enums/ConnectionSettings.swift
+++ b/IVPNClient/Enums/ConnectionSettings.swift
@@ -30,6 +30,10 @@ enum ConnectionSettings {
case wireguard(WireGuardProtocol, Int)
func format() -> String {
+ if UserDefaults.shared.isMultiHop {
+ return formatMultiHop()
+ }
+
switch self {
case .ipsec:
return "IKEv2"
@@ -56,7 +60,7 @@ enum ConnectionSettings {
case .udp:
return "OpenVPN, UDP"
}
- case .wireguard(_, _):
+ case .wireguard:
return "WireGuard, UDP"
}
}
@@ -137,7 +141,7 @@ enum ConnectionSettings {
}
func supportedProtocolsFormat(protocols: [ConnectionSettings]) -> [String] {
- let protocols = supportedProtocols(protocols: Config.supportedProtocols)
+ let protocols = supportedProtocols(protocols: protocols)
return protocols.map({ $0.formatProtocol() })
}
@@ -146,11 +150,41 @@ enum ConnectionSettings {
}
static func getSavedProtocol() -> ConnectionSettings {
- let protocolIndex = UserDefaults.standard.integer(forKey: UserDefaults.Key.selectedProtocolIndex)
+ let portString = UserDefaults.standard.string(forKey: UserDefaults.Key.selectedProtocol) ?? ""
+ return getFrom(portString: portString)
+ }
+
+ static func getFrom(portString: String) -> ConnectionSettings {
+ var name = ""
+ var proto = ""
+ var port = 0
+ let components = portString.components(separatedBy: "-")
+
+ if let protocolName = components[safeIndex: 0] {
+ name = protocolName
+ }
+ if let protocolType = components[safeIndex: 1] {
+ proto = protocolType
+ }
+ if let protocolPort = components[safeIndex: 2] {
+ port = Int(protocolPort) ?? 0
+ }
- if Config.supportedProtocols.indices.contains(protocolIndex) && UserDefaults.standard.object(forKey: UserDefaults.Key.selectedProtocolIndex) != nil || !(KeyChain.sessionToken ?? "").isEmpty {
- return Config.supportedProtocols[protocolIndex]
- } else {
+ switch name {
+ case "ikev2":
+ return .ipsec
+ case "openvpn":
+ switch proto {
+ case "tcp":
+ return .openvpn(.tcp, port)
+ case "udp":
+ return .openvpn(.udp, port)
+ default:
+ return Config.defaultProtocol
+ }
+ case "wireguard":
+ return .wireguard(.udp, port)
+ default:
return Config.defaultProtocol
}
}
diff --git a/IVPNClient/Managers/APIClient.swift b/IVPNClient/Managers/APIClient.swift
index 5a1f610e0..ab2a89c03 100644
--- a/IVPNClient/Managers/APIClient.swift
+++ b/IVPNClient/Managers/APIClient.swift
@@ -152,6 +152,12 @@ class APIClient: NSObject {
urlComponents.path = baseURL.path
urlComponents.queryItems = request.queryItems
+ // TODO: Remove when fixed in future iOS versions
+ // https://github.com/ivpn/ios-app/issues/276
+ if #available(iOS 16.0, *), let addressType = request.addressType, addressType == .IPv6 {
+ urlComponents.host = "[\(hostName)]"
+ }
+
if request.method == .post {
urlComponents.queryItems = []
}
diff --git a/IVPNClient/Managers/ConnectionManager.swift b/IVPNClient/Managers/ConnectionManager.swift
index e9c427d25..7b1d73185 100644
--- a/IVPNClient/Managers/ConnectionManager.swift
+++ b/IVPNClient/Managers/ConnectionManager.swift
@@ -533,7 +533,7 @@ class ConnectionManager {
}
getWireGuardLog { _ in
- var wireGuardLog: String? = nil
+ var wireGuardLog: String?
let filePath = FileSystemManager.sharedFilePath(name: "WireGuard.log").path
if let file = NSData(contentsOfFile: filePath) {
wireGuardLog = String(data: file as Data, encoding: .utf8) ?? ""
diff --git a/IVPNClient/Managers/NavigationManager.swift b/IVPNClient/Managers/NavigationManager.swift
index d236bc6ec..d51d6b16b 100644
--- a/IVPNClient/Managers/NavigationManager.swift
+++ b/IVPNClient/Managers/NavigationManager.swift
@@ -181,4 +181,16 @@ class NavigationManager {
return navController!
}
+ static func getAddCustomPortViewController(delegate: AddCustomPortViewControllerDelegate? = nil) -> UIViewController {
+ let storyBoard = UIStoryboard(name: "Main", bundle: nil)
+ let navController = storyBoard.instantiateViewController(withIdentifier: "addCustomPort") as? UINavigationController
+ navController?.modalPresentationStyle = .formSheet
+
+ if let viewController = navController?.topViewController as? AddCustomPortViewController {
+ viewController.delegate = delegate
+ }
+
+ return navController!
+ }
+
}
diff --git a/IVPNClient/Managers/SessionManager.swift b/IVPNClient/Managers/SessionManager.swift
index 8a47b3544..6b2806e82 100644
--- a/IVPNClient/Managers/SessionManager.swift
+++ b/IVPNClient/Managers/SessionManager.swift
@@ -123,6 +123,7 @@ class SessionManager {
switch result {
case .success(let model):
Application.shared.serviceStatus = model.serviceStatus
+ NotificationCenter.default.post(name: Notification.Name.EvaluatePlanUpdate, object: nil)
if model.serviceActive {
self.delegate?.sessionStatusSuccess()
diff --git a/IVPNClient/Managers/StorageManager.swift b/IVPNClient/Managers/StorageManager.swift
index 12ecff8aa..9d162299f 100644
--- a/IVPNClient/Managers/StorageManager.swift
+++ b/IVPNClient/Managers/StorageManager.swift
@@ -58,6 +58,7 @@ class StorageManager {
static func clearSession() {
remove(entityName: "Network")
remove(entityName: "Server")
+ remove(entityName: "CustomPort")
}
static func remove(entityName: String) {
@@ -154,6 +155,29 @@ extension StorageManager {
}
}
+ static func saveCustomPort(vpnProtocol: String = "", type: String = "", port: Int = 0) {
+ let customPort = CustomPort(context: context)
+ customPort.vpnProtocol = vpnProtocol
+ customPort.type = type
+ customPort.port = Int32(port)
+ saveContext()
+ }
+
+ static func fetchCustomPorts(vpnProtocol: String = "") -> [CustomPort]? {
+ let request: NSFetchRequest = CustomPort.fetchRequest(vpnProtocol: vpnProtocol)
+
+ do {
+ let result = try context.fetch(request)
+ if !result.isEmpty {
+ return result
+ }
+ } catch {
+ log(error: "Coult not load collection from StorageManager")
+ }
+
+ return nil
+ }
+
}
// MARK: - NEOnDemandRule -
diff --git a/IVPNClient/Managers/VPNManager.swift b/IVPNClient/Managers/VPNManager.swift
index b28134166..9303a42a4 100644
--- a/IVPNClient/Managers/VPNManager.swift
+++ b/IVPNClient/Managers/VPNManager.swift
@@ -413,7 +413,7 @@ class VPNManager {
}
do {
- try session.sendProviderMessage(Message.requestLog.data) { data in
+ try session.sendProviderMessage(Message.requestLog.data) { _ in
completion(nil)
return
}
diff --git a/IVPNClient/Model.xcdatamodeld/Model.xcdatamodel/contents b/IVPNClient/Model.xcdatamodeld/Model.xcdatamodel/contents
index e44f7e53d..4a78cee8f 100644
--- a/IVPNClient/Model.xcdatamodeld/Model.xcdatamodel/contents
+++ b/IVPNClient/Model.xcdatamodeld/Model.xcdatamodel/contents
@@ -1,5 +1,10 @@
-
+
+
+
+
+
+
@@ -10,8 +15,4 @@
-
-
-
-
\ No newline at end of file
diff --git a/IVPNClient/Models/CoreData/CustomPort+CoreDataClass.swift b/IVPNClient/Models/CoreData/CustomPort+CoreDataClass.swift
new file mode 100644
index 000000000..92573ebf5
--- /dev/null
+++ b/IVPNClient/Models/CoreData/CustomPort+CoreDataClass.swift
@@ -0,0 +1,30 @@
+//
+// CustomPort+CoreDataClass.swift
+// IVPN iOS app
+// https://github.com/ivpn/ios-app
+//
+// Created by Juraj Hilje on 2022-10-05.
+// Copyright (c) 2022 Privatus Limited.
+//
+// This file is part of the IVPN iOS app.
+//
+// The IVPN iOS app is free software: you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as published by the Free
+// Software Foundation, either version 3 of the License, or (at your option) any later version.
+//
+// The IVPN iOS app is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+// details.
+//
+// You should have received a copy of the GNU General Public License
+// along with the IVPN iOS app. If not, see .
+//
+
+import Foundation
+import CoreData
+
+@objc(CustomPort)
+public class CustomPort: NSManagedObject {
+
+}
diff --git a/IVPNClient/Models/CoreData/CustomPort+CoreDataProperties.swift b/IVPNClient/Models/CoreData/CustomPort+CoreDataProperties.swift
new file mode 100644
index 000000000..db1e2d64e
--- /dev/null
+++ b/IVPNClient/Models/CoreData/CustomPort+CoreDataProperties.swift
@@ -0,0 +1,46 @@
+//
+// CustomPort+CoreDataProperties.swift
+// IVPN iOS app
+// https://github.com/ivpn/ios-app
+//
+// Created by Juraj Hilje on 2022-10-05.
+// Copyright (c) 2022 Privatus Limited.
+//
+// This file is part of the IVPN iOS app.
+//
+// The IVPN iOS app is free software: you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as published by the Free
+// Software Foundation, either version 3 of the License, or (at your option) any later version.
+//
+// The IVPN iOS app is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+// details.
+//
+// You should have received a copy of the GNU General Public License
+// along with the IVPN iOS app. If not, see .
+//
+
+import Foundation
+import CoreData
+
+extension CustomPort {
+
+ @NSManaged public var vpnProtocol: String?
+ @NSManaged public var type: String?
+ @NSManaged public var port: Int32
+
+ @nonobjc public class func fetchRequest(vpnProtocol: String = "") -> NSFetchRequest {
+ let fetchRequest = NSFetchRequest(entityName: "CustomPort")
+ var filters = [NSPredicate]()
+
+ if !vpnProtocol.isEmpty {
+ filters.append(NSPredicate(format: "vpnProtocol == %@", vpnProtocol))
+ }
+
+ fetchRequest.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: filters)
+
+ return fetchRequest
+ }
+
+}
diff --git a/IVPNClient/Models/Host.swift b/IVPNClient/Models/Host.swift
index e62b1adef..1b62c7f87 100644
--- a/IVPNClient/Models/Host.swift
+++ b/IVPNClient/Models/Host.swift
@@ -23,17 +23,19 @@
import Foundation
-struct IPv6 {
+struct IPv6: Codable {
var localIP: String
}
-struct Host {
+struct Host: Codable {
var host: String
+ var hostName: String
var publicKey: String
var localIP: String
var ipv6: IPv6?
var multihopPort: Int
+ var load: Double
func localIPAddress() -> String {
if let range = localIP.range(of: "/", options: .backwards, range: nil, locale: nil) {
@@ -44,4 +46,34 @@ struct Host {
return ""
}
+ func hostNamePrefix() -> String {
+ let hostNameParts = hostName.components(separatedBy: ".")
+ if let location = hostNameParts.first {
+ return location
+ }
+
+ return ""
+ }
+
+ static func save(_ host: Host?, key: String) {
+ if let host = host {
+ if let encoded = try? JSONEncoder().encode(host) {
+ UserDefaults.standard.set(encoded, forKey: key)
+ }
+ } else {
+ UserDefaults.standard.removeObject(forKey: key)
+ }
+ UserDefaults.standard.synchronize()
+ }
+
+ static func load(key: String) -> Host? {
+ if let saved = UserDefaults.standard.object(forKey: key) as? Data {
+ if let loaded = try? JSONDecoder().decode(Host.self, from: saved) {
+ return loaded
+ }
+ }
+
+ return nil
+ }
+
}
diff --git a/IVPNClient/Models/PortRange.swift b/IVPNClient/Models/PortRange.swift
new file mode 100644
index 000000000..36c87f87f
--- /dev/null
+++ b/IVPNClient/Models/PortRange.swift
@@ -0,0 +1,90 @@
+//
+// PortRange.swift
+// IVPN iOS app
+// https://github.com/ivpn/ios-app
+//
+// Created by Juraj Hilje on 2022-07-15.
+// Copyright (c) 2022 Privatus Limited.
+//
+// This file is part of the IVPN iOS app.
+//
+// The IVPN iOS app is free software: you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as published by the Free
+// Software Foundation, either version 3 of the License, or (at your option) any later version.
+//
+// The IVPN iOS app is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+// details.
+//
+// You should have received a copy of the GNU General Public License
+// along with the IVPN iOS app. If not, see .
+//
+
+import Foundation
+
+struct PortRange {
+
+ // MARK: - Properties -
+
+ var tunnelType: String
+ var protocolType: String
+ var ranges: [CountableClosedRange]
+
+ var portRangesText: String {
+ let combinedRanges = PortRange.combinedIntervals(intervals: ranges.sorted { $0.lowerBound < $1.lowerBound })
+ var textRanges = [String]()
+
+ for range in combinedRanges {
+ textRanges.append("\(String(describing: range.first ?? 0)) - \(String(describing: range.last ?? 0))")
+ }
+
+ return textRanges.joined(separator: ", ")
+ }
+
+ // MARK: - Methods -
+
+ func validate(port: Int) -> String? {
+ for range in ranges {
+ if range.contains(port) {
+ return nil
+ }
+ }
+
+ return "Enter port number in the range: \(portRangesText)"
+ }
+
+ static func combinedIntervals(intervals: [CountableClosedRange]) -> [CountableClosedRange] {
+ var combined = [CountableClosedRange]()
+ var accumulator = (0...0) // empty range
+
+ for interval in intervals.sorted(by: { $0.lowerBound < $1.lowerBound } ) {
+
+ if accumulator == (0...0) {
+ accumulator = interval
+ }
+
+ if accumulator.upperBound >= interval.upperBound {
+ // interval is already inside accumulator
+ }
+
+ else if accumulator.upperBound + 1 >= interval.lowerBound {
+ // interval hangs off the back end of accumulator
+ accumulator = (accumulator.lowerBound...interval.upperBound)
+ }
+
+ else if accumulator.upperBound <= interval.lowerBound {
+ // interval does not overlap
+ combined.append(accumulator)
+ accumulator = interval
+ }
+ }
+
+ if accumulator != (0...0) {
+ combined.append(accumulator)
+ }
+
+ return combined
+ }
+
+}
diff --git a/IVPNClient/Models/Service.swift b/IVPNClient/Models/Service.swift
index af3bd190a..b9018b2b2 100644
--- a/IVPNClient/Models/Service.swift
+++ b/IVPNClient/Models/Service.swift
@@ -146,7 +146,7 @@ struct Service {
return duration.willBeActiveUntilFrom(date: date)
}
- // Methods
+ // MARK: - Methods -
static func == (lhs: Service, rhs: Service) -> Bool {
return (lhs.type == rhs.type && lhs.duration == rhs.duration)
diff --git a/IVPNClient/Models/ServiceStatus.swift b/IVPNClient/Models/ServiceStatus.swift
index 427aedf38..cc3ad9af8 100644
--- a/IVPNClient/Models/ServiceStatus.swift
+++ b/IVPNClient/Models/ServiceStatus.swift
@@ -60,9 +60,9 @@ struct ServiceStatus: Codable {
}
static func load() -> ServiceStatus? {
- if let savedObj = UserDefaults.standard.object(forKey: UserDefaults.Key.serviceStatus) as? Data {
- if let loadedObj = try? JSONDecoder().decode(ServiceStatus.self, from: savedObj) {
- return loadedObj
+ if let saved = UserDefaults.standard.object(forKey: UserDefaults.Key.serviceStatus) as? Data {
+ if let loaded = try? JSONDecoder().decode(ServiceStatus.self, from: saved) {
+ return loaded
}
}
diff --git a/IVPNClient/Models/Settings.swift b/IVPNClient/Models/Settings.swift
index 22e2f0077..f3137bddf 100644
--- a/IVPNClient/Models/Settings.swift
+++ b/IVPNClient/Models/Settings.swift
@@ -26,6 +26,8 @@ import NetworkExtension
class Settings {
+ // MARK: - Properties -
+
var selectedServer: VPNServer {
didSet {
UserDefaults.standard.set(selectedServer.gateway, forKey: UserDefaults.Key.selectedServerGateway)
@@ -44,11 +46,25 @@ class Settings {
}
}
+ var selectedHost: Host? {
+ didSet {
+ Host.save(selectedHost, key: UserDefaults.Key.selectedHost)
+ }
+ }
+
+ var selectedExitHost: Host? {
+ didSet {
+ Host.save(selectedExitHost, key: UserDefaults.Key.selectedExitHost)
+ }
+ }
+
var connectionProtocol: ConnectionSettings {
didSet {
saveConnectionProtocol()
}
}
+
+ // MARK: - Initialize -
init(serverList: VPNServerList) {
connectionProtocol = ConnectionSettings.getSavedProtocol()
@@ -91,8 +107,18 @@ class Settings {
if let status = NEVPNStatus.init(rawValue: UserDefaults.standard.integer(forKey: UserDefaults.Key.selectedServerStatus)) {
selectedServer.status = status
}
+
+ if selectedHost == nil {
+ selectedHost = Host.load(key: UserDefaults.Key.selectedHost)
+ }
+
+ if selectedExitHost == nil {
+ selectedExitHost = Host.load(key: UserDefaults.Key.selectedExitHost)
+ }
}
+ // MARK: - Methods -
+
func updateSelectedServerForMultiHop(isEnabled: Bool) {
if isEnabled && Application.shared.settings.selectedServer.fastest {
if let server = Application.shared.serverList.getServers().first {
@@ -118,10 +144,6 @@ class Settings {
}
func saveConnectionProtocol() {
- if let index = Config.supportedProtocols.firstIndex(where: {$0 == connectionProtocol}) {
- UserDefaults.standard.set(index, forKey: UserDefaults.Key.selectedProtocolIndex)
- }
-
UserDefaults.standard.set(connectionProtocol.formatSave(), forKey: UserDefaults.Key.selectedProtocol)
}
diff --git a/IVPNClient/Models/VPNServer.swift b/IVPNClient/Models/VPNServer.swift
index f27a24dfb..30c51621a 100644
--- a/IVPNClient/Models/VPNServer.swift
+++ b/IVPNClient/Models/VPNServer.swift
@@ -78,6 +78,14 @@ class VPNServer {
return false
}
+ var isHost: Bool {
+ return country == "" && gateway != ""
+ }
+
+ var hostGateway: String {
+ return gateway.components(separatedBy: CharacterSet.decimalDigits).joined()
+ }
+
private (set) var gateway: String
private (set) var countryCode: String
private (set) var country: String
@@ -86,10 +94,11 @@ class VPNServer {
private (set) var longitude: Double
private (set) var ipAddresses: [String]
private (set) var hosts: [Host]
+ private (set) var load: Double?
// MARK: - Initialize -
- init(gateway: String, countryCode: String, country: String, city: String, latitude: Double = 0, longitude: Double = 0, ipAddresses: [String] = [], hosts: [Host] = [], fastest: Bool = false) {
+ init(gateway: String, countryCode: String, country: String, city: String, latitude: Double = 0, longitude: Double = 0, ipAddresses: [String] = [], hosts: [Host] = [], fastest: Bool = false, load: Double = 0) {
self.gateway = gateway
self.countryCode = countryCode
self.country = country
@@ -99,6 +108,7 @@ class VPNServer {
self.ipAddresses = ipAddresses
self.hosts = hosts
self.fastest = fastest
+ self.load = load
}
// MARK: - Methods -
@@ -113,6 +123,14 @@ class VPNServer {
return location.distance(from: self.location)
}
+ func getHost(hostName: String) -> Host? {
+ return hosts.first { $0.hostName == hostName }
+ }
+
+ func getHost(fromPrefix: String) -> Host? {
+ return hosts.first { $0.hostName.hasPrefix(fromPrefix) }
+ }
+
static func == (lhs: VPNServer, rhs: VPNServer) -> Bool {
return lhs.city == rhs.city && lhs.countryCode == rhs.countryCode
}
diff --git a/IVPNClient/Models/VPNServerList.swift b/IVPNClient/Models/VPNServerList.swift
index 0328e880d..a7e011bd4 100644
--- a/IVPNClient/Models/VPNServerList.swift
+++ b/IVPNClient/Models/VPNServerList.swift
@@ -31,6 +31,8 @@ class VPNServerList {
// MARK: - Properties -
open private(set) var servers: [VPNServer]
+ open private(set) var ports: [ConnectionSettings]
+ open private(set) var portRanges: [PortRange]
var filteredFastestServers: [VPNServer] {
var serversArray = getServers()
@@ -84,6 +86,8 @@ class VPNServerList {
// and optionally save it to the cache file for later access
init(withJSONData data: Data?, storeInCache: Bool = false) {
servers = [VPNServer]()
+ ports = [ConnectionSettings]()
+ portRanges = [PortRange]()
if let jsonData = data {
var serversList: [[String: Any]]?
@@ -140,6 +144,55 @@ class VPNServerList {
UserDefaults.shared.set(ips, forKey: UserDefaults.Key.ipv6HostNames)
}
}
+
+ if let portsObj = config["ports"] as? [String: Any] {
+ ports.append(ConnectionSettings.ipsec)
+
+ if let openvpn = portsObj["openvpn"] as? [[String: Any]] {
+ var udpRanges = [CountableClosedRange]()
+ var tcpRanges = [CountableClosedRange]()
+ for port in openvpn {
+ if let portNumber = port["port"] as? Int {
+ if port["type"] as? String == "TCP" {
+ ports.append(ConnectionSettings.openvpn(.tcp, portNumber))
+ } else {
+ ports.append(ConnectionSettings.openvpn(.udp, portNumber))
+ }
+ }
+ if let range = port["range"] as? [String: Any] {
+ if let min = range["min"] as? Int, let max = range["max"] as? Int {
+ if port["type"] as? String == "TCP" {
+ tcpRanges.append(min...max)
+ } else {
+ udpRanges.append(min...max)
+ }
+ }
+ }
+ }
+ if !udpRanges.isEmpty {
+ portRanges.append(PortRange(tunnelType: "OpenVPN", protocolType: "UDP", ranges: udpRanges))
+ }
+ if !tcpRanges.isEmpty {
+ portRanges.append(PortRange(tunnelType: "OpenVPN", protocolType: "TCP", ranges: tcpRanges))
+ }
+ }
+ if let wireguard = portsObj["wireguard"] as? [[String: Any]] {
+ var ranges = [CountableClosedRange]()
+ for port in wireguard {
+ if let portNumber = port["port"] as? Int {
+ ports.append(ConnectionSettings.wireguard(.udp, portNumber))
+ }
+ if let range = port["range"] as? [String: Any] {
+ if let min = range["min"] as? Int, let max = range["max"] as? Int {
+ ranges.append(min...max)
+ }
+ }
+ }
+ if !ranges.isEmpty {
+ portRanges.append(PortRange(tunnelType: "WireGuard", protocolType: "UDP", ranges: ranges))
+ }
+ }
+ }
}
}
}
@@ -166,6 +219,25 @@ class VPNServerList {
return servers
}
+ func getAllHosts(_ servers: [VPNServer]? = nil) -> [VPNServer] {
+ var allHosts: [VPNServer] = []
+ let allServers = servers ?? getServers()
+
+ for server in allServers {
+ if server.isHost {
+ continue
+ }
+
+ allHosts.append(server)
+
+ for host in server.hosts {
+ allHosts.append(VPNServer(gateway: host.hostName, countryCode: server.countryCode, country: "", city: server.city, load: host.load))
+ }
+ }
+
+ return allHosts
+ }
+
func getServer(byIpAddress ipAddress: String) -> VPNServer? {
return getServers().first { $0.ipAddresses.first { $0 == ipAddress } != nil }
}
@@ -178,6 +250,22 @@ class VPNServerList {
return getServers().first { $0.city == city }
}
+ func getServer(byPrefix prefix: String) -> VPNServer? {
+ return getAllHosts().first { $0.gateway.hasPrefix(prefix) }
+ }
+
+ func getHost(_ host: Host?) -> Host? {
+ guard let host = host else {
+ return nil
+ }
+
+ if let serverHost = getServer(byPrefix: host.hostNamePrefix()), let server = getServer(byCity: serverHost.city) {
+ return server.getHost(fromPrefix: host.hostNamePrefix())
+ }
+
+ return nil
+ }
+
func getFastestServer() -> VPNServer? {
let servers = filteredFastestServers
if noPing {
@@ -233,6 +321,10 @@ class VPNServerList {
servers = VPNServerList.sort(servers)
}
+ func getPortRanges(tunnelType: String) -> [PortRange] {
+ return portRanges.filter { $0.tunnelType == tunnelType }
+ }
+
static func sort(_ servers: [VPNServer]) -> [VPNServer] {
let sort = ServersSort.init(rawValue: UserDefaults.shared.serversSort)
var servers = servers
@@ -274,9 +366,11 @@ class VPNServerList {
var newHost = Host(
host: host["host"] as? String ?? "",
+ hostName: host["hostname"] as? String ?? "",
publicKey: host["public_key"] as? String ?? "",
localIP: host["local_ip"] as? String ?? "",
- multihopPort: host["multihop_port"] as? Int ?? 0
+ multihopPort: host["multihop_port"] as? Int ?? 0,
+ load: host["load"] as? Double ?? 0
)
if let ipv6 = host["ipv6"] as? [String: Any] {
diff --git a/IVPNClient/Scenes/Base.lproj/Main.storyboard b/IVPNClient/Scenes/Base.lproj/Main.storyboard
index 809e85fe3..cb8bf942d 100644
--- a/IVPNClient/Scenes/Base.lproj/Main.storyboard
+++ b/IVPNClient/Scenes/Base.lproj/Main.storyboard
@@ -1,9 +1,10 @@
-
+
-
+
+
@@ -20,7 +21,7 @@
-
+
-
+
@@ -800,22 +845,37 @@
-
+
-
-
+
+
-
+
-
+
+
+
@@ -951,7 +1014,7 @@
-
+
@@ -988,14 +1051,14 @@
-
+
-
+
-
+
@@ -1013,14 +1076,14 @@
-
+
-
+
-
+
@@ -1029,7 +1092,7 @@
-
+
@@ -1039,7 +1102,7 @@
-
+
@@ -1132,7 +1195,7 @@
-
+
@@ -1160,7 +1223,7 @@
-
+
@@ -1196,7 +1259,7 @@
-
+
@@ -1232,7 +1295,7 @@
-
+
@@ -1268,7 +1331,7 @@
-
+
@@ -1311,7 +1374,7 @@
-
+
@@ -1344,7 +1407,7 @@
-
+
@@ -1413,7 +1476,7 @@
-
+
@@ -1450,7 +1513,7 @@
-
+
@@ -1510,14 +1573,14 @@
-
+
-
+
-
+
@@ -1526,7 +1589,7 @@
-
+
@@ -1548,7 +1611,7 @@
-
+
@@ -1610,6 +1673,7 @@
+
@@ -1628,7 +1692,7 @@
-
+
@@ -1679,7 +1743,7 @@
-
+
@@ -1730,7 +1794,7 @@
-
+
@@ -1766,7 +1830,7 @@
-
+
@@ -1802,7 +1866,7 @@
-
+
@@ -1843,7 +1907,7 @@
Using the same internal IP address and keys for extended period of time may not be ideal for various reasons when connected with WireGuard protocol.
-
+
@@ -1889,7 +1953,216 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1937,7 +2210,7 @@
-
+
@@ -1982,7 +2255,7 @@
-
+
@@ -2024,23 +2297,23 @@
-
+
-
+
-
+
-
+
-
+
@@ -2050,13 +2323,13 @@
-
+
-
+
@@ -2073,7 +2346,7 @@
-
+
@@ -2081,7 +2354,7 @@
-
+
@@ -2120,23 +2393,23 @@
-
+
-
+
-
+
-
+
-
+
@@ -2169,7 +2442,7 @@
-
+
@@ -2189,7 +2462,7 @@
-
+
@@ -2214,7 +2487,7 @@
-
+
@@ -2262,14 +2535,14 @@
-
+
-
+
-
+
@@ -2289,7 +2562,7 @@
-
+
@@ -2322,26 +2595,26 @@
-
+
-
+
-
+
-
+
-
+
-
+
@@ -2361,7 +2634,7 @@
-
+
@@ -2654,7 +2927,7 @@
-
+
@@ -2835,7 +3108,7 @@
-
+
@@ -2931,7 +3204,7 @@
-
+
@@ -3043,7 +3316,7 @@
-
+
@@ -3068,7 +3341,7 @@
-
+
@@ -3104,7 +3377,7 @@
-
+
@@ -3137,7 +3410,7 @@
-
+
@@ -3173,7 +3446,7 @@
-
+
@@ -3209,7 +3482,7 @@
-
+
@@ -3321,7 +3594,7 @@
Hardcore mode blocks the leading companies with business models relying on user surveillance (currently: Google and Facebook). Learn more
-
+
@@ -3453,21 +3726,21 @@
-
+
-
+
-
+
@@ -3477,7 +3750,7 @@
-
+
@@ -3620,7 +3893,7 @@
-
+