* allow custom upstream dns
* default upstream dns to quad9 * add upstream dns field in ui * refactor LokinetDaemon.java to use static final strings for defaults instead of literals * keep it on flutter 1.x because flutter 2.x broke lmao
This commit is contained in:
parent
24be74e3de
commit
edbc6abfe3
|
@ -6,7 +6,7 @@ An app to interact with Lokinet as a vpn tunnel for android
|
|||
|
||||
build requirements:
|
||||
|
||||
* flutter 2.x
|
||||
* flutter 1.x (ideally flutter 2.x if you are able to)
|
||||
* lokinet android jni libs
|
||||
|
||||
first you need to get a build of the native libs for android lokinet
|
||||
|
|
|
@ -51,7 +51,7 @@ class LokinetHomePageState extends State<LokinetHomePage> {
|
|||
Widget build(BuildContext context) {
|
||||
final key = new GlobalKey<ScaffoldState>();
|
||||
|
||||
bool darkModeOn = inDarkMode(context);
|
||||
final bool darkModeOn = inDarkMode(context);
|
||||
|
||||
return Scaffold(
|
||||
key: key,
|
||||
|
@ -73,7 +73,8 @@ class MyFormState extends State<MyForm> {
|
|||
static final key = new GlobalKey<FormState>();
|
||||
Timer _timer;
|
||||
bool isConnected = false;
|
||||
final textInput = TextEditingController();
|
||||
final exitInput = TextEditingController();
|
||||
final dnsInput = TextEditingController();
|
||||
|
||||
void _startTimer() {
|
||||
const halfSec = Duration(milliseconds: 50);
|
||||
|
@ -102,10 +103,10 @@ class MyFormState extends State<MyForm> {
|
|||
await LokinetLib.disconnectFromLokinet();
|
||||
await _cancelTimer();
|
||||
} else {
|
||||
String exitNode = textInput.value.text.trim();
|
||||
if (exitNode == "") exitNode = "exit.loki";
|
||||
final String exitNode = exitInput.value.text.trim();
|
||||
final String upstreamDNS = dnsInput.value.text.trim();
|
||||
final result = await LokinetLib.prepareConnection();
|
||||
if (result) LokinetLib.connectToLokinet(exitNode: exitNode);
|
||||
if (result) LokinetLib.connectToLokinet(exitNode: exitNode, upstreamDNS: upstreamDNS);
|
||||
_startTimer();
|
||||
}
|
||||
}
|
||||
|
@ -124,25 +125,50 @@ class MyFormState extends State<MyForm> {
|
|||
LokinetDivider(),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 45, right: 45),
|
||||
child: TextFormField(
|
||||
validator: (value) {
|
||||
final trimmed = value.trim();
|
||||
if (trimmed == "") return null;
|
||||
if (trimmed == ".loki" || !trimmed.endsWith(".loki"))
|
||||
child:
|
||||
TextFormField(
|
||||
validator: (value) {
|
||||
final trimmed = value.trim();
|
||||
if (trimmed == "") return null;
|
||||
if (trimmed == ".loki" || !trimmed.endsWith(".loki"))
|
||||
return "Invalid exit node value";
|
||||
return null;
|
||||
},
|
||||
controller: textInput,
|
||||
cursorColor: color,
|
||||
decoration: InputDecoration(
|
||||
return null;
|
||||
},
|
||||
controller: exitInput,
|
||||
cursorColor: color,
|
||||
decoration: InputDecoration(
|
||||
filled: true,
|
||||
fillColor: darkModeOn
|
||||
? Color.fromARGB(255, 35, 35, 35)
|
||||
: Color.fromARGB(255, 226, 226, 226),
|
||||
? Color.fromARGB(255, 35, 35, 35)
|
||||
: Color.fromARGB(255, 226, 226, 226),
|
||||
border: InputBorder.none,
|
||||
labelStyle: TextStyle(color: color),
|
||||
labelText: 'Exit Node'),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 45, right: 45),
|
||||
child:
|
||||
TextFormField(
|
||||
validator: (value) {
|
||||
final trimmed = value.trim();
|
||||
if (trimmed == "") return null;
|
||||
RegExp re = RegExp(r'^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$');
|
||||
if (!re.hasMatch(trimmed))
|
||||
return "DNS server does not look like an IP";
|
||||
return null;
|
||||
},
|
||||
controller: dnsInput,
|
||||
cursorColor: color,
|
||||
decoration: InputDecoration(
|
||||
filled: true,
|
||||
fillColor: darkModeOn
|
||||
? Color.fromARGB(255, 35, 35, 35)
|
||||
: Color.fromARGB(255, 226, 226, 226),
|
||||
border: InputBorder.none,
|
||||
labelStyle: TextStyle(color: color),
|
||||
labelText: 'UpstreamDNS'),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.all(20),
|
||||
|
|
|
@ -16,6 +16,11 @@ public class LokinetDaemon extends VpnService {
|
|||
public static final String LOG_TAG = "LokinetDaemon";
|
||||
public static final String MESSAGE_CHANNEL = "LOKINET_DAEMON";
|
||||
public static final String EXIT_NODE = "EXIT_NODE";
|
||||
public static final String UPSTREAM_DNS = "UPSTREAM_DNS";
|
||||
|
||||
|
||||
private static final String DEFAULT_EXIT_NODE = "exit.loki";
|
||||
private static final String DEFAULT_UPSTREAM_DNS = "9.9.9.9";
|
||||
|
||||
static {
|
||||
System.loadLibrary("lokinet-android");
|
||||
|
@ -67,14 +72,24 @@ public class LokinetDaemon extends VpnService {
|
|||
} else {
|
||||
String exitNode = intent.getStringExtra(EXIT_NODE);
|
||||
|
||||
if (exitNode == null) {
|
||||
Log.e(LOG_TAG, "No exit-node configured! Proceeding with exit.loki.");
|
||||
exitNode = "exit.loki";
|
||||
if (exitNode == null || exitNode.isEmpty()) {
|
||||
exitNode = DEFAULT_EXIT_NODE;
|
||||
Log.e(LOG_TAG, "No exit-node configured! Proceeding with default.");
|
||||
}
|
||||
|
||||
Log.e(LOG_TAG, "Using " + exitNode + " as exit-node.");
|
||||
|
||||
boolean connectedSucessfully = connect(exitNode);
|
||||
String upstreamDNS = intent.getStringExtra(UPSTREAM_DNS);
|
||||
|
||||
if (upstreamDNS == null || upstreamDNS.isEmpty()) {
|
||||
upstreamDNS = DEFAULT_UPSTREAM_DNS;
|
||||
Log.e(LOG_TAG, "No upstream DNS configured! Proceeding with default.");
|
||||
}
|
||||
|
||||
Log.e(LOG_TAG, "Using " + upstreamDNS + " as upstream DNS.");
|
||||
|
||||
|
||||
boolean connectedSucessfully = connect(exitNode, upstreamDNS);
|
||||
if (connectedSucessfully)
|
||||
return START_STICKY;
|
||||
else
|
||||
|
@ -82,7 +97,7 @@ public class LokinetDaemon extends VpnService {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean connect(String exitNode) {
|
||||
private boolean connect(String exitNode, String upstreamDNS) {
|
||||
if (!IsRunning()) {
|
||||
if (impl != null) {
|
||||
Free(impl);
|
||||
|
@ -103,7 +118,6 @@ public class LokinetDaemon extends VpnService {
|
|||
return false;
|
||||
}
|
||||
|
||||
String upstreamDNS = "1.1.1.1";
|
||||
String ourRange = DetectFreeRange();
|
||||
|
||||
if (ourRange.isEmpty()) {
|
||||
|
|
|
@ -78,10 +78,12 @@ class LokinetLibPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
|
|||
}
|
||||
|
||||
val exitNode = call.argument<String>("exit_node")
|
||||
val upstreamDNS = call.argument<String>("upstream_dns")
|
||||
|
||||
val lokinetIntent = Intent(activityBinding.activity.applicationContext, LokinetDaemon::class.java)
|
||||
lokinetIntent.action = LokinetDaemon.ACTION_CONNECT
|
||||
lokinetIntent.putExtra(LokinetDaemon.EXIT_NODE, exitNode)
|
||||
lokinetIntent.putExtra(LokinetDaemon.UPSTREAM_DNS, upstreamDNS)
|
||||
|
||||
activityBinding.activity.applicationContext.startService(lokinetIntent)
|
||||
doBindService()
|
||||
|
|
|
@ -29,9 +29,9 @@ class LokinetLib {
|
|||
return prepare;
|
||||
}
|
||||
|
||||
static Future<bool> connectToLokinet({String exitNode = "exit.loki"}) async {
|
||||
static Future<bool> connectToLokinet({String exitNode = "exit.loki", String upstreamDNS="9.9.9.9"}) async {
|
||||
final bool connect =
|
||||
await _channel.invokeMethod('connect', {"exit_node": exitNode});
|
||||
await _channel.invokeMethod('connect', {"exit_node": exitNode, "upstream_dns": upstreamDNS});
|
||||
return connect;
|
||||
}
|
||||
|
||||
|
|
47
pubspec.lock
47
pubspec.lock
|
@ -21,42 +21,42 @@ packages:
|
|||
name: async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.5.0"
|
||||
version: "2.5.0-nullsafety.1"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
version: "2.1.0-nullsafety.1"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: characters
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
version: "1.1.0-nullsafety.3"
|
||||
charcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: charcode
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.2.0-nullsafety.1"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
version: "1.1.0-nullsafety.1"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.15.0"
|
||||
version: "1.15.0-nullsafety.3"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -84,7 +84,7 @@ packages:
|
|||
name: fake_async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.2.0-nullsafety.1"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -135,13 +135,6 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.16.1"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.6.3"
|
||||
lokinet_lib:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -155,21 +148,21 @@ packages:
|
|||
name: matcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.12.10"
|
||||
version: "0.12.10-nullsafety.1"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
version: "1.3.0-nullsafety.3"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.0"
|
||||
version: "1.8.0-nullsafety.1"
|
||||
path_provider:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -286,56 +279,56 @@ packages:
|
|||
name: source_span
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.0"
|
||||
version: "1.8.0-nullsafety.2"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
version: "1.10.0-nullsafety.1"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
version: "2.1.0-nullsafety.1"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
version: "1.1.0-nullsafety.1"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.2.0-nullsafety.1"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.19"
|
||||
version: "0.2.19-nullsafety.2"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
version: "1.3.0-nullsafety.3"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
version: "2.1.0-nullsafety.3"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -365,5 +358,5 @@ packages:
|
|||
source: hosted
|
||||
version: "2.2.1"
|
||||
sdks:
|
||||
dart: ">=2.12.0-0.0 <3.0.0"
|
||||
flutter: ">=1.20.0"
|
||||
dart: ">=2.10.0-110 <2.11.0"
|
||||
flutter: ">=1.20.0 <2.0.0"
|
||||
|
|
Loading…
Reference in New Issue