* 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:
Jeff Becker 2021-06-20 05:46:43 -04:00
parent 24be74e3de
commit edbc6abfe3
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05
6 changed files with 88 additions and 53 deletions

View File

@ -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

View File

@ -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),

View File

@ -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()) {

View File

@ -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()

View File

@ -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;
}

View File

@ -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"