Merge pull request #44 from passepartoutvpn/diagnose-debug-masking
Diagnose debug masking
This commit is contained in:
commit
57f8104f27
|
@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Added
|
||||
|
||||
- Configure masking in debug log for improved diagnostics.
|
||||
|
||||
## 1.1.0 (2019-03-22)
|
||||
|
||||
### Added
|
||||
|
|
|
@ -109,16 +109,16 @@ class OrganizerViewController: UITableViewController, TableModelHost {
|
|||
override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
if !didShowSubreddit && !TransientStore.shared.didHandleSubreddit {
|
||||
if !didShowSubreddit && !TransientStore.didHandleSubreddit {
|
||||
didShowSubreddit = true
|
||||
|
||||
let alert = Macros.alert(L10n.Reddit.title, L10n.Reddit.message)
|
||||
alert.addDefaultAction(L10n.Reddit.Buttons.subscribe) {
|
||||
TransientStore.shared.didHandleSubreddit = true
|
||||
TransientStore.didHandleSubreddit = true
|
||||
self.subscribeSubreddit()
|
||||
}
|
||||
alert.addAction(L10n.Reddit.Buttons.never) {
|
||||
TransientStore.shared.didHandleSubreddit = true
|
||||
TransientStore.didHandleSubreddit = true
|
||||
}
|
||||
alert.addCancelAction(L10n.Reddit.Buttons.remind)
|
||||
present(alert, animated: true, completion: nil)
|
||||
|
|
|
@ -48,6 +48,8 @@ class ServiceViewController: UIViewController, TableModelHost {
|
|||
|
||||
private var lastInfrastructureUpdate: Date?
|
||||
|
||||
private var shouldDeleteLogOnDisconnection = false
|
||||
|
||||
// MARK: Table
|
||||
|
||||
var model: TableModel<SectionType, RowType> = TableModel()
|
||||
|
@ -358,7 +360,7 @@ class ServiceViewController: UIViewController, TableModelHost {
|
|||
|
||||
private func testInternetConnectivity() {
|
||||
let hud = HUD()
|
||||
Utils.checkConnectivityURL(AppConstants.VPN.connectivityURL, timeout: AppConstants.VPN.connectivityTimeout) {
|
||||
Utils.checkConnectivityURL(AppConstants.Web.connectivityURL, timeout: AppConstants.Web.connectivityTimeout) {
|
||||
hud.hide()
|
||||
|
||||
let V = L10n.Service.Alerts.TestConnectivity.Messages.self
|
||||
|
@ -397,6 +399,34 @@ class ServiceViewController: UIViewController, TableModelHost {
|
|||
self.present(alert, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
private func togglePrivateDataMasking(cell: ToggleTableViewCell) {
|
||||
let handler = {
|
||||
TransientStore.masksPrivateData = cell.isOn
|
||||
self.service.baseConfiguration = TransientStore.baseVPNConfiguration.build()
|
||||
}
|
||||
|
||||
guard vpn.status == .disconnected else {
|
||||
let alert = Macros.alert(
|
||||
L10n.Service.Cells.MasksPrivateData.caption,
|
||||
L10n.Service.Alerts.MasksPrivateData.Messages.mustReconnect
|
||||
)
|
||||
alert.addDestructiveAction(L10n.Service.Alerts.Buttons.reconnect) {
|
||||
handler()
|
||||
self.shouldDeleteLogOnDisconnection = true
|
||||
self.vpn.reconnect(completionHandler: nil)
|
||||
}
|
||||
alert.addCancelAction(L10n.Global.cancel) {
|
||||
cell.setOn(!cell.isOn, animated: true)
|
||||
}
|
||||
present(alert, animated: true, completion: nil)
|
||||
return
|
||||
}
|
||||
|
||||
handler()
|
||||
service.eraseVpnLog()
|
||||
shouldDeleteLogOnDisconnection = false
|
||||
}
|
||||
|
||||
private func postSupportRequest() {
|
||||
UIApplication.shared.open(AppConstants.URLs.subreddit, options: [:], completionHandler: nil)
|
||||
|
@ -412,8 +442,21 @@ class ServiceViewController: UIViewController, TableModelHost {
|
|||
@objc private func vpnDidUpdate() {
|
||||
reloadVpnStatus()
|
||||
|
||||
if vpn.status == .connected {
|
||||
guard let status = vpn.status else {
|
||||
return
|
||||
}
|
||||
switch status {
|
||||
case .connected:
|
||||
Reviewer.shared.reportEvent()
|
||||
|
||||
case .disconnected:
|
||||
if shouldDeleteLogOnDisconnection {
|
||||
service.eraseVpnLog()
|
||||
shouldDeleteLogOnDisconnection = false
|
||||
}
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -493,6 +536,8 @@ extension ServiceViewController: UITableViewDataSource, UITableViewDelegate, Tog
|
|||
|
||||
case debugLog
|
||||
|
||||
case masksPrivateData
|
||||
|
||||
case joinCommunity
|
||||
|
||||
case reportIssue
|
||||
|
@ -705,6 +750,12 @@ extension ServiceViewController: UITableViewDataSource, UITableViewDelegate, Tog
|
|||
cell.leftText = L10n.Service.Cells.DebugLog.caption
|
||||
return cell
|
||||
|
||||
case .masksPrivateData:
|
||||
let cell = Cells.toggle.dequeue(from: tableView, for: indexPath, tag: row.rawValue, delegate: self)
|
||||
cell.caption = L10n.Service.Cells.MasksPrivateData.caption
|
||||
cell.isOn = TransientStore.masksPrivateData
|
||||
return cell
|
||||
|
||||
// feedback
|
||||
|
||||
case .joinCommunity:
|
||||
|
@ -859,6 +910,9 @@ extension ServiceViewController: UITableViewDataSource, UITableViewDelegate, Tog
|
|||
case .trustedPolicy:
|
||||
toggleTrustedConnectionPolicy(cell.isOn, sender: cell)
|
||||
|
||||
case .masksPrivateData:
|
||||
togglePrivateDataMasking(cell: cell)
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
@ -922,6 +976,7 @@ extension ServiceViewController: UITableViewDataSource, UITableViewDelegate, Tog
|
|||
}
|
||||
model.setFooter(L10n.Service.Sections.VpnSurvivesSleep.footer, for: .vpnSurvivesSleep)
|
||||
model.setFooter(L10n.Service.Sections.Trusted.footer, for: .trustedPolicy)
|
||||
model.setFooter(L10n.Service.Sections.Diagnostics.footer, for: .diagnostics)
|
||||
}
|
||||
|
||||
// rows
|
||||
|
@ -947,7 +1002,7 @@ extension ServiceViewController: UITableViewDataSource, UITableViewDelegate, Tog
|
|||
}
|
||||
model.set([.vpnSurvivesSleep], in: .vpnSurvivesSleep)
|
||||
model.set([.trustedPolicy], in: .trustedPolicy)
|
||||
model.set([.dataCount, .debugLog], in: .diagnostics)
|
||||
model.set([.dataCount, .debugLog, .masksPrivateData], in: .diagnostics)
|
||||
model.set([.joinCommunity, .reportIssue], in: .feedback)
|
||||
}
|
||||
|
||||
|
|
|
@ -79,6 +79,7 @@
|
|||
"service.sections.trusted.header" = "Trusted networks";
|
||||
"service.sections.trusted.footer" = "When entering a trusted network, the VPN is normally shut down and kept disconnected. Disable this option to not enforce such behavior.";
|
||||
"service.sections.diagnostics.header" = "Diagnostics";
|
||||
"service.sections.diagnostics.footer" = "Masking status will be effective after reconnecting. Network data is hostnames, IP addresses, routing, SSID. Credentials and private keys are not logged regardless.";
|
||||
//"service.sections.destruction.footer" = "Delete configuration from device settings.";
|
||||
|
||||
"service.cells.use_profile.caption" = "Use this profile";
|
||||
|
@ -106,6 +107,7 @@
|
|||
"service.cells.test_connectivity.caption" = "Test connectivity";
|
||||
"service.cells.data_count.caption" = "Exchanged bytes count";
|
||||
"service.cells.debug_log.caption" = "Debug log";
|
||||
"service.cells.masks_private_data.caption" = "Mask network data";
|
||||
"service.cells.report_issue.caption" = "Report connectivity issue";
|
||||
|
||||
"service.alerts.rename.title" = "Rename profile";
|
||||
|
@ -119,6 +121,8 @@
|
|||
"service.alerts.test_connectivity.messages.failure" = "Your device has no Internet connectivity, please review your profile parameters.";
|
||||
"service.alerts.data_count.messages.current" = "Received: %llu\nSent: %llu";
|
||||
"service.alerts.data_count.messages.not_available" = "Information not available, are you connected?";
|
||||
"service.alerts.masks_private_data.messages.must_reconnect" = "In order to safely reset the current debug log and apply the new masking preference, you must reconnect to the VPN now.";
|
||||
"service.alerts.buttons.reconnect" = "Reconnect";
|
||||
|
||||
"account.cells.username.caption" = "Username";
|
||||
"account.cells.username.placeholder" = "username";
|
||||
|
|
|
@ -46,31 +46,6 @@ public class AppConstants {
|
|||
public static let hostsDirectory = "Hosts"
|
||||
}
|
||||
|
||||
public class VPN {
|
||||
public static func baseConfiguration() -> TunnelKitProvider.Configuration {
|
||||
let sessionBuilder = SessionProxy.ConfigurationBuilder(ca: CryptoContainer(pem: ""))
|
||||
var builder = TunnelKitProvider.ConfigurationBuilder(sessionConfiguration: sessionBuilder.build())
|
||||
builder.mtu = 1250
|
||||
builder.shouldDebug = true
|
||||
// builder.debugLogFormat = "$Dyyyy-MM-dd HH:mm:ss.SSS$d $L $N.$F:$l - $M"
|
||||
// builder.debugLogFormat = "$DHH:mm:ss$d $N.$F:$l - $M"
|
||||
builder.debugLogFormat = Log.debugFormat
|
||||
return builder.build()
|
||||
}
|
||||
|
||||
private static let connectivityStrings: [String] = [
|
||||
"https://www.amazon.com",
|
||||
"https://www.google.com",
|
||||
"https://www.twitter.com",
|
||||
"https://www.facebook.com",
|
||||
"https://www.instagram.com"
|
||||
]
|
||||
|
||||
public static let connectivityURL = URL(string: connectivityStrings.customRandomElement())!
|
||||
|
||||
public static let connectivityTimeout: TimeInterval = 10.0
|
||||
}
|
||||
|
||||
public class Web {
|
||||
private static let version = "v1"
|
||||
|
||||
|
@ -83,6 +58,18 @@ public class AppConstants {
|
|||
public static let timeout: TimeInterval = 3.0
|
||||
|
||||
public static let minimumUpdateInterval: TimeInterval = 600.0 // 10 minutes
|
||||
|
||||
private static let connectivityStrings: [String] = [
|
||||
"https://www.amazon.com",
|
||||
"https://www.google.com",
|
||||
"https://www.twitter.com",
|
||||
"https://www.facebook.com",
|
||||
"https://www.instagram.com"
|
||||
]
|
||||
|
||||
public static let connectivityURL = URL(string: connectivityStrings.customRandomElement())!
|
||||
|
||||
public static let connectivityTimeout: TimeInterval = 10.0
|
||||
}
|
||||
|
||||
public class Log {
|
||||
|
|
|
@ -510,7 +510,11 @@ public class ConnectionService: Codable {
|
|||
baseConfiguration.clearLastError(in: appGroup)
|
||||
}
|
||||
|
||||
// public func eraseVpnLog() {
|
||||
// defaults.removeObject(forKey: Keys.vpnLog)
|
||||
// }
|
||||
public func eraseVpnLog() {
|
||||
log.info("Erasing VPN log...")
|
||||
guard let url = baseConfiguration.urlForLog(in: appGroup) else {
|
||||
return
|
||||
}
|
||||
try? FileManager.default.removeItem(at: url)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,6 +62,7 @@ public class HostConnectionProfile: ConnectionProfile, Codable, Equatable {
|
|||
builder.mtu = configuration.mtu
|
||||
builder.shouldDebug = configuration.shouldDebug
|
||||
builder.debugLogFormat = configuration.debugLogFormat
|
||||
builder.masksPrivateData = configuration.masksPrivateData
|
||||
|
||||
return builder.build()
|
||||
}
|
||||
|
|
|
@ -119,6 +119,7 @@ public class ProviderConnectionProfile: ConnectionProfile, Codable, Equatable {
|
|||
builder.mtu = configuration.mtu
|
||||
builder.shouldDebug = configuration.shouldDebug
|
||||
builder.debugLogFormat = configuration.debugLogFormat
|
||||
builder.masksPrivateData = configuration.masksPrivateData
|
||||
|
||||
if let address = manualAddress {
|
||||
builder.prefersResolvedAddresses = true
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import TunnelKit
|
||||
import SwiftyBeaver
|
||||
|
||||
private let log = SwiftyBeaver.self
|
||||
|
@ -31,6 +32,8 @@ private let log = SwiftyBeaver.self
|
|||
public class TransientStore {
|
||||
private struct Keys {
|
||||
static let didHandleSubreddit = "DidHandleSubreddit"
|
||||
|
||||
static let masksPrivateData = "MasksPrivateData"
|
||||
}
|
||||
|
||||
public static let shared = TransientStore()
|
||||
|
@ -41,7 +44,7 @@ public class TransientStore {
|
|||
|
||||
public let service: ConnectionService
|
||||
|
||||
public var didHandleSubreddit: Bool {
|
||||
public static var didHandleSubreddit: Bool {
|
||||
get {
|
||||
return UserDefaults.standard.bool(forKey: Keys.didHandleSubreddit)
|
||||
}
|
||||
|
@ -50,13 +53,39 @@ public class TransientStore {
|
|||
}
|
||||
}
|
||||
|
||||
public static var masksPrivateData: Bool {
|
||||
get {
|
||||
return UserDefaults.standard.bool(forKey: Keys.masksPrivateData)
|
||||
}
|
||||
set {
|
||||
UserDefaults.standard.set(newValue, forKey: Keys.masksPrivateData)
|
||||
}
|
||||
}
|
||||
|
||||
public static var baseVPNConfiguration: TunnelKitProvider.ConfigurationBuilder {
|
||||
let sessionBuilder = SessionProxy.ConfigurationBuilder(ca: CryptoContainer(pem: ""))
|
||||
var builder = TunnelKitProvider.ConfigurationBuilder(sessionConfiguration: sessionBuilder.build())
|
||||
builder.mtu = 1250
|
||||
builder.shouldDebug = true
|
||||
// builder.debugLogFormat = "$Dyyyy-MM-dd HH:mm:ss.SSS$d $L $N.$F:$l - $M"
|
||||
// builder.debugLogFormat = "$DHH:mm:ss$d $N.$F:$l - $M"
|
||||
builder.debugLogFormat = AppConstants.Log.debugFormat
|
||||
builder.masksPrivateData = masksPrivateData
|
||||
return builder
|
||||
}
|
||||
|
||||
private init() {
|
||||
UserDefaults.standard.register(defaults: [
|
||||
Keys.didHandleSubreddit: false,
|
||||
Keys.masksPrivateData: true
|
||||
])
|
||||
|
||||
TransientStore.migrateDocumentsToAppGroup()
|
||||
|
||||
// this must be graceful
|
||||
ConnectionService.migrateJSON(from: TransientStore.serviceURL, to: TransientStore.serviceURL)
|
||||
|
||||
let cfg = AppConstants.VPN.baseConfiguration()
|
||||
let cfg = TransientStore.baseVPNConfiguration.build()
|
||||
do {
|
||||
let data = try Data(contentsOf: TransientStore.serviceURL)
|
||||
if let content = String(data: data, encoding: .utf8) {
|
||||
|
|
|
@ -454,6 +454,10 @@ public enum L10n {
|
|||
|
||||
public enum Service {
|
||||
public enum Alerts {
|
||||
public enum Buttons {
|
||||
/// Reconnect
|
||||
public static let reconnect = L10n.tr("Localizable", "service.alerts.buttons.reconnect")
|
||||
}
|
||||
public enum CredentialsNeeded {
|
||||
/// You need to enter account credentials first.
|
||||
public static let message = L10n.tr("Localizable", "service.alerts.credentials_needed.message")
|
||||
|
@ -468,6 +472,12 @@ public enum L10n {
|
|||
public static let notAvailable = L10n.tr("Localizable", "service.alerts.data_count.messages.not_available")
|
||||
}
|
||||
}
|
||||
public enum MasksPrivateData {
|
||||
public enum Messages {
|
||||
/// In order to safely reset the current debug log and apply the new masking preference, you must reconnect to the VPN now.
|
||||
public static let mustReconnect = L10n.tr("Localizable", "service.alerts.masks_private_data.messages.must_reconnect")
|
||||
}
|
||||
}
|
||||
public enum ReconnectVpn {
|
||||
/// Do you want to reconnect to the VPN?
|
||||
public static let message = L10n.tr("Localizable", "service.alerts.reconnect_vpn.message")
|
||||
|
@ -546,6 +556,10 @@ public enum L10n {
|
|||
}
|
||||
}
|
||||
}
|
||||
public enum MasksPrivateData {
|
||||
/// Mask network data
|
||||
public static let caption = L10n.tr("Localizable", "service.cells.masks_private_data.caption")
|
||||
}
|
||||
public enum Provider {
|
||||
public enum Pool {
|
||||
/// Location
|
||||
|
@ -613,6 +627,8 @@ public enum L10n {
|
|||
public static let header = L10n.tr("Localizable", "service.sections.configuration.header")
|
||||
}
|
||||
public enum Diagnostics {
|
||||
/// Masking status will be effective after reconnecting. Network data is hostnames, IP addresses, routing, SSID. Credentials and private keys are not logged regardless.
|
||||
public static let footer = L10n.tr("Localizable", "service.sections.diagnostics.footer")
|
||||
/// Diagnostics
|
||||
public static let header = L10n.tr("Localizable", "service.sections.diagnostics.header")
|
||||
}
|
||||
|
|
8
Podfile
8
Podfile
|
@ -3,10 +3,10 @@ platform :ios, '11.0'
|
|||
use_frameworks!
|
||||
|
||||
def shared_pods
|
||||
pod 'TunnelKit', '~> 1.5.0'
|
||||
pod 'TunnelKit/LZO', '~> 1.5.0'
|
||||
#pod 'TunnelKit', :git => 'https://github.com/keeshux/tunnelkit', :commit => '2f17e30'
|
||||
#pod 'TunnelKit/LZO', :git => 'https://github.com/keeshux/tunnelkit', :commit => '2f17e30'
|
||||
#pod 'TunnelKit', '~> 1.5.0'
|
||||
#pod 'TunnelKit/LZO', '~> 1.5.0'
|
||||
pod 'TunnelKit', :git => 'https://github.com/keeshux/tunnelkit', :commit => '04fbbb1'
|
||||
pod 'TunnelKit/LZO', :git => 'https://github.com/keeshux/tunnelkit', :commit => '04fbbb1'
|
||||
#pod 'TunnelKit', :path => '../../personal/tunnelkit'
|
||||
#pod 'TunnelKit/LZO', :path => '../../personal/tunnelkit'
|
||||
end
|
||||
|
|
31
Podfile.lock
31
Podfile.lock
|
@ -2,35 +2,44 @@ PODS:
|
|||
- MBProgressHUD (1.1.0)
|
||||
- OpenSSL-Apple (1.1.0i.2)
|
||||
- SwiftyBeaver (1.6.2)
|
||||
- TunnelKit (1.5.0):
|
||||
- TunnelKit/AppExtension (= 1.5.0)
|
||||
- TunnelKit/Core (= 1.5.0)
|
||||
- TunnelKit/AppExtension (1.5.0):
|
||||
- TunnelKit (1.5.1):
|
||||
- TunnelKit/AppExtension (= 1.5.1)
|
||||
- TunnelKit/Core (= 1.5.1)
|
||||
- TunnelKit/AppExtension (1.5.1):
|
||||
- SwiftyBeaver
|
||||
- TunnelKit/Core
|
||||
- TunnelKit/Core (1.5.0):
|
||||
- TunnelKit/Core (1.5.1):
|
||||
- OpenSSL-Apple (~> 1.1.0i.2)
|
||||
- SwiftyBeaver
|
||||
- TunnelKit/LZO (1.5.0)
|
||||
- TunnelKit/LZO (1.5.1)
|
||||
|
||||
DEPENDENCIES:
|
||||
- MBProgressHUD
|
||||
- TunnelKit (~> 1.5.0)
|
||||
- TunnelKit/LZO (~> 1.5.0)
|
||||
- TunnelKit (from `https://github.com/keeshux/tunnelkit`, commit `04fbbb1`)
|
||||
- TunnelKit/LZO (from `https://github.com/keeshux/tunnelkit`, commit `04fbbb1`)
|
||||
|
||||
SPEC REPOS:
|
||||
https://github.com/cocoapods/specs.git:
|
||||
- MBProgressHUD
|
||||
- OpenSSL-Apple
|
||||
- SwiftyBeaver
|
||||
- TunnelKit
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
TunnelKit:
|
||||
:commit: 04fbbb1
|
||||
:git: https://github.com/keeshux/tunnelkit
|
||||
|
||||
CHECKOUT OPTIONS:
|
||||
TunnelKit:
|
||||
:commit: 04fbbb1
|
||||
:git: https://github.com/keeshux/tunnelkit
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
MBProgressHUD: e7baa36a220447d8aeb12769bf0585582f3866d9
|
||||
OpenSSL-Apple: 37a8c0b04df4bb8971deef4671cc29222861319c
|
||||
SwiftyBeaver: 8e67ab3cd94389cbbb7a9c7cc02748d98bfee68e
|
||||
TunnelKit: bfe0960fc09d9e69cc66a141084887c5abf986d4
|
||||
TunnelKit: fb4db4d4c4b36af0ca8e973e3345a1c3ef5ac85c
|
||||
|
||||
PODFILE CHECKSUM: 5cab612f9d6b322c13311ce6b0aa1f7939a6e818
|
||||
PODFILE CHECKSUM: 1b84c62ece95cae765c64491d65dab9333db2381
|
||||
|
||||
COCOAPODS: 1.6.1
|
||||
|
|
Loading…
Reference in New Issue