add disable openvpnconnection, refactoring
This commit is contained in:
parent
6c2e6ead2b
commit
28ae7eeaee
8 changed files with 500 additions and 482 deletions
|
|
@ -29,94 +29,95 @@ import net.openvpn.ovpn3.ClientAPI_TransportStats
|
||||||
class OpenVPNThreadv3(var service: VPNService): ClientAPI_OpenVPNClient(), Runnable {
|
class OpenVPNThreadv3(var service: VPNService): ClientAPI_OpenVPNClient(), Runnable {
|
||||||
private val tag = "OpenVPNThreadv3"
|
private val tag = "OpenVPNThreadv3"
|
||||||
private var mConfig: JSONObject? = null
|
private var mConfig: JSONObject? = null
|
||||||
private var mConnectionTime: Long = 0
|
|
||||||
private var mAlreadyInitialised = false
|
private var mAlreadyInitialised = false
|
||||||
private var mService: VPNService = service
|
private var mService: VPNService = service
|
||||||
|
|
||||||
private var currentTunnelHandle = -1
|
|
||||||
|
|
||||||
override fun run() {
|
override fun run() {
|
||||||
//TEMP
|
//TEMP
|
||||||
|
|
||||||
val lConfigData: String = readFileDirectlyAsText("/data/local/tmp/android_conf.ovpn")
|
|
||||||
val config: ClientAPI_Config = ClientAPI_Config()
|
val config: ClientAPI_Config = ClientAPI_Config()
|
||||||
config.content = lConfigData
|
config.content = mService.getVpnConfig().getString("openvpn_config_data")
|
||||||
|
|
||||||
val lCreds: ClientAPI_ProvideCreds = ClientAPI_ProvideCreds()
|
|
||||||
//username from config or GUI
|
|
||||||
lCreds.username = ""
|
|
||||||
//password from config or GUI
|
|
||||||
lCreds.password = ""
|
|
||||||
|
|
||||||
provide_creds(lCreds)
|
|
||||||
|
|
||||||
eval_config(config)
|
eval_config(config)
|
||||||
connect()
|
val status = connect()
|
||||||
Log.i(tag, "Connect succesfully")
|
Log.i(tag, "ERROR " + status)
|
||||||
|
if (status.getError() != false) {
|
||||||
|
Log.i(tag, "connect() error: " + status.getError() + ": " + status.getMessage())
|
||||||
|
mService.openvpnConnected()
|
||||||
|
} else {
|
||||||
|
Log.i(tag, "Connect succesfully, OpenVPN3 thread finished")
|
||||||
|
mService.openvpnConnected()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun log(arg0: ClientAPI_LogInfo){
|
||||||
|
Log.i(tag, arg0.getText())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun event(event: ClientAPI_Event ){
|
||||||
|
Log.i(tag, event.getName())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun tun_builder_new(): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun tun_builder_establish(): Int {
|
||||||
|
Log.v(tag, "tun_builder_establish")
|
||||||
|
return mService.establish()!!.detachFd()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun tun_builder_add_address(address: String , prefix_length: Int , gateway: String , ipv6:Boolean , net30: Boolean ): Boolean {
|
||||||
|
Log.v(tag, "tun_builder_add_address")
|
||||||
|
mService.addAddress(address, prefix_length)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun tun_builder_add_route(address: String, prefix_length: Int, metric: Int, ipv6: Boolean): Boolean {
|
||||||
|
Log.v(tag, "tun_builder_add_route")
|
||||||
|
if (address.equals("remote_host"))
|
||||||
|
return false
|
||||||
|
|
||||||
|
mService.addRoute(address, prefix_length);
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun tun_builder_exclude_route(address: String, prefix_length: Int, metric: Int, ipv6: Boolean): Boolean {
|
||||||
|
if (address.equals("remote_host"))
|
||||||
|
return false
|
||||||
|
|
||||||
|
mService.addRoute(address, prefix_length);
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun tun_builder_set_remote_address(address: String , ipv6: Boolean): Boolean {
|
||||||
|
mService.setMtu(1500)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun tun_builder_set_mtu(mtu: Int): Boolean {
|
||||||
|
Log.v(tag, "tun_builder_set_mtu")
|
||||||
|
mService.setMtu(mtu)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun tun_builder_add_dns_server(address: String , ipv6: Boolean): Boolean {
|
||||||
|
mService.addDNS(address)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun tun_builder_set_session_name(name: String ): Boolean {
|
||||||
|
Log.v(tag, "We should call this session: " + name)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun stopVPN(): Boolean {
|
||||||
|
stop()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun stop() {
|
||||||
|
super.stop()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun readFileDirectlyAsText(fileName: String): String = File(fileName).readText(Charsets.UTF_8)
|
|
||||||
|
|
||||||
override fun log(arg0: ClientAPI_LogInfo){
|
|
||||||
Log.i(tag, arg0.getText())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun event(event: ClientAPI_Event ){
|
|
||||||
Log.i(tag, event.getName())
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override fun tun_builder_new(): Boolean {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun tun_builder_establish(): Int {
|
|
||||||
Log.v(tag, "tun_builder_establish")
|
|
||||||
return mService.establish()!!.detachFd()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun tun_builder_add_address(address: String , prefix_length: Int , gateway: String , ipv6:Boolean , net30: Boolean ): Boolean {
|
|
||||||
Log.v(tag, "tun_builder_add_address")
|
|
||||||
mService.addAddress(address, prefix_length)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun tun_builder_add_route(address: String, prefix_length: Int, metric: Int, ipv6: Boolean): Boolean {
|
|
||||||
Log.v(tag, "tun_builder_add_route")
|
|
||||||
if (address.equals("remote_host"))
|
|
||||||
return false
|
|
||||||
|
|
||||||
mService.addRoute(address, prefix_length);
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun tun_builder_exclude_route(address: String, prefix_length: Int, metric: Int, ipv6: Boolean): Boolean {
|
|
||||||
if (address.equals("remote_host"))
|
|
||||||
return false
|
|
||||||
|
|
||||||
mService.addRoute(address, prefix_length);
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun tun_builder_set_remote_address(address: String , ipv6: Boolean): Boolean {
|
|
||||||
mService.setMtu(1500)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun tun_builder_set_mtu(mtu: Int): Boolean {
|
|
||||||
Log.v(tag, "tun_builder_set_mtu")
|
|
||||||
mService.setMtu(mtu)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun tun_builder_add_dns_server(address: String , ipv6: Boolean): Boolean {
|
|
||||||
mService.addDNS(address)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun tun_builder_set_session_name(name: String ): Boolean {
|
|
||||||
Log.v(tag, "We should call this session: " + name)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -19,11 +19,11 @@ class VPNService : android.net.VpnService() {
|
||||||
private val tag = "VPNService"
|
private val tag = "VPNService"
|
||||||
private var mBinder: VPNServiceBinder = VPNServiceBinder(this)
|
private var mBinder: VPNServiceBinder = VPNServiceBinder(this)
|
||||||
private var mConfig: JSONObject? = null
|
private var mConfig: JSONObject? = null
|
||||||
|
private var mProtocol: String? = null
|
||||||
private var mConnectionTime: Long = 0
|
private var mConnectionTime: Long = 0
|
||||||
private var mAlreadyInitialised = false
|
private var mAlreadyInitialised = false
|
||||||
private var mbuilder: Builder = Builder()
|
private var mbuilder: Builder = Builder()
|
||||||
|
|
||||||
|
|
||||||
private var mOpenVPNThreadv3: OpenVPNThreadv3? = null
|
private var mOpenVPNThreadv3: OpenVPNThreadv3? = null
|
||||||
private var currentTunnelHandle = -1
|
private var currentTunnelHandle = -1
|
||||||
|
|
||||||
|
|
@ -67,293 +67,302 @@ class VPNService : android.net.VpnService() {
|
||||||
*/
|
*/
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
init()
|
init()
|
||||||
// intent?.let {
|
intent?.let {
|
||||||
// if (intent.getBooleanExtra("startOnly", false)) {
|
if (intent.getBooleanExtra("startOnly", false)) {
|
||||||
// Log.i(tag, "Start only!")
|
Log.i(tag, "Start only!")
|
||||||
// return super.onStartCommand(intent, flags, startId)
|
return super.onStartCommand(intent, flags, startId)
|
||||||
// }
|
}
|
||||||
// }
|
|
||||||
// // This start is from always-on
|
|
||||||
// if (this.mConfig == null) {
|
|
||||||
// // We don't have tunnel to turn on - Try to create one with last config the service got
|
|
||||||
// val prefs = Prefs.get(this)
|
|
||||||
// val lastConfString = prefs.getString("lastConf", "")
|
|
||||||
// if (lastConfString.isNullOrEmpty()) {
|
|
||||||
// // We have nothing to connect to -> Exit
|
|
||||||
// Log.e(
|
|
||||||
// tag,
|
|
||||||
// "VPN service was triggered without defining a Server or having a tunnel"
|
|
||||||
// )
|
|
||||||
// return super.onStartCommand(intent, flags, startId)
|
|
||||||
// }
|
|
||||||
// this.mConfig = JSONObject(lastConfString)
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// Log.v(tag, "onStartCommand:" + this.mConfig)
|
|
||||||
// turnOn(this.mConfig)
|
|
||||||
|
|
||||||
return super.onStartCommand(intent, flags, startId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invoked when the application is revoked.
|
|
||||||
// At this moment, the VPN interface is already deactivated by the system.
|
|
||||||
override fun onRevoke() {
|
|
||||||
this.turnOff()
|
|
||||||
super.onRevoke()
|
|
||||||
}
|
|
||||||
|
|
||||||
var connectionTime: Long = 0
|
|
||||||
get() {
|
|
||||||
return mConnectionTime
|
|
||||||
}
|
|
||||||
|
|
||||||
var isUp: Boolean
|
|
||||||
get() {
|
|
||||||
return currentTunnelHandle >= 0
|
|
||||||
}
|
|
||||||
private set(value) {
|
|
||||||
if (value) {
|
|
||||||
mBinder.dispatchEvent(VPNServiceBinder.EVENTS.connected, "")
|
|
||||||
mConnectionTime = System.currentTimeMillis()
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
mBinder.dispatchEvent(VPNServiceBinder.EVENTS.disconnected, "")
|
// This start is from always-on
|
||||||
mConnectionTime = 0
|
if (this.mConfig == null) {
|
||||||
}
|
// We don't have tunnel to turn on - Try to create one with last config the service got
|
||||||
val status: JSONObject
|
val prefs = Prefs.get(this)
|
||||||
get() {
|
val lastConfString = prefs.getString("lastConf", "")
|
||||||
val deviceIpv4: String = ""
|
if (lastConfString.isNullOrEmpty()) {
|
||||||
return JSONObject().apply {
|
// We have nothing to connect to -> Exit
|
||||||
putOpt("rx_bytes", getConfigValue("rx_bytes"))
|
Log.e(
|
||||||
putOpt("tx_bytes", getConfigValue("tx_bytes"))
|
tag,
|
||||||
putOpt("endpoint", mConfig?.getJSONObject("server")?.getString("ipv4Gateway"))
|
"VPN service was triggered without defining a Server or having a tunnel"
|
||||||
putOpt("deviceIpv4", mConfig?.getJSONObject("device")?.getString("ipv4Address"))
|
)
|
||||||
}
|
return super.onStartCommand(intent, flags, startId)
|
||||||
}
|
}
|
||||||
/*
|
this.mConfig = JSONObject(lastConfString)
|
||||||
* Checks if the VPN Permission is given.
|
}
|
||||||
* If the permission is given, returns true
|
|
||||||
* Requests permission and returns false if not.
|
|
||||||
*/
|
|
||||||
fun checkPermissions(): Boolean {
|
|
||||||
// See https://developer.android.com/guide/topics/connectivity/vpn#connect_a_service
|
|
||||||
// Call Prepare, if we get an Intent back, we dont have the VPN Permission
|
|
||||||
// from the user. So we need to pass this to our main Activity and exit here.
|
|
||||||
val intent = prepare(this)
|
|
||||||
if (intent == null) {
|
|
||||||
Log.e(tag, "VPN Permission Already Present")
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
Log.e(tag, "Requesting VPN Permission")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun turnOn(json: JSONObject?): ParcelFileDescriptor? {
|
return super.onStartCommand(intent, flags, startId)
|
||||||
Log.sensitive(tag, "" + json.toString())
|
}
|
||||||
// val wireguard_conf = buildWireugardConfig(json)
|
|
||||||
|
// Invoked when the application is revoked.
|
||||||
|
// At this moment, the VPN interface is already deactivated by the system.
|
||||||
|
override fun onRevoke() {
|
||||||
|
this.turnOff()
|
||||||
|
super.onRevoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
var connectionTime: Long = 0
|
||||||
|
get() {
|
||||||
|
return mConnectionTime
|
||||||
|
}
|
||||||
|
|
||||||
|
var isUp: Boolean
|
||||||
|
get() {
|
||||||
|
return currentTunnelHandle >= 0
|
||||||
|
}
|
||||||
|
private set(value) {
|
||||||
|
if (value) {
|
||||||
|
mBinder.dispatchEvent(VPNServiceBinder.EVENTS.connected, "")
|
||||||
|
mConnectionTime = System.currentTimeMillis()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mBinder.dispatchEvent(VPNServiceBinder.EVENTS.disconnected, "")
|
||||||
|
mConnectionTime = 0
|
||||||
|
}
|
||||||
|
val status: JSONObject
|
||||||
|
get() {
|
||||||
|
val deviceIpv4: String = ""
|
||||||
|
return JSONObject().apply {
|
||||||
|
putOpt("rx_bytes", getConfigValue("rx_bytes"))
|
||||||
|
putOpt("tx_bytes", getConfigValue("tx_bytes"))
|
||||||
|
putOpt("endpoint", mConfig?.getJSONObject("server")?.getString("ipv4Gateway"))
|
||||||
|
putOpt("deviceIpv4", mConfig?.getJSONObject("device")?.getString("ipv4Address"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Checks if the VPN Permission is given.
|
||||||
|
* If the permission is given, returns true
|
||||||
|
* Requests permission and returns false if not.
|
||||||
|
*/
|
||||||
|
fun checkPermissions(): Boolean {
|
||||||
|
// See https://developer.android.com/guide/topics/connectivity/vpn#connect_a_service
|
||||||
|
// Call Prepare, if we get an Intent back, we dont have the VPN Permission
|
||||||
|
// from the user. So we need to pass this to our main Activity and exit here.
|
||||||
|
val intent = prepare(this)
|
||||||
|
if (intent == null) {
|
||||||
|
Log.e(tag, "VPN Permission Already Present")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
Log.e(tag, "Requesting VPN Permission")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun turnOn(json: JSONObject?): Int {
|
||||||
|
if (!checkPermissions()) {
|
||||||
|
Log.e(tag, "turn on was called without no permissions present!")
|
||||||
|
isUp = false
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
Log.i(tag, "Permission okay")
|
||||||
|
mConfig = json
|
||||||
|
mProtocol = mConfig!!.getString("protocol")
|
||||||
|
when (mProtocol) {
|
||||||
|
"openvpn" -> startOpenVpn()
|
||||||
|
"wireguard" -> startWireGuard()
|
||||||
|
else -> {
|
||||||
|
Log.e(tag, "No protocol")
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fun establish(): ParcelFileDescriptor? {
|
||||||
|
return mbuilder.establish()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setMtu(mtu: Int) {
|
||||||
|
mbuilder.setMtu(mtu)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addAddress(ip: String, len: Int){
|
||||||
|
mbuilder.addAddress(ip, len)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addRoute(ip: String, len: Int){
|
||||||
|
mbuilder.addRoute(ip, len)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addDNS(ip: String){
|
||||||
|
mbuilder.addDnsServer(ip)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun turnOff() {
|
||||||
|
Log.v(tag, "Try to disable tunnel")
|
||||||
|
when(mProtocol){
|
||||||
|
"wireguard" -> wgTurnOff(currentTunnelHandle)
|
||||||
|
"openvpn" -> mOpenVPNThreadv3?.stopVPN()
|
||||||
|
else -> {
|
||||||
|
Log.e(tag, "No protocol")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentTunnelHandle = -1
|
||||||
|
stopForeground(true)
|
||||||
|
|
||||||
if (!checkPermissions()) {
|
|
||||||
Log.e(tag, "turn on was called without no permissions present!")
|
|
||||||
isUp = false
|
isUp = false
|
||||||
return null
|
stopSelf();
|
||||||
}
|
}
|
||||||
// Log.i(tag, "Permission okay")
|
|
||||||
// if (currentTunnelHandle != -1) {
|
|
||||||
// Log.e(tag, "Tunnel already up")
|
|
||||||
// // Turn the tunnel down because this might be a switch
|
|
||||||
// wgTurnOff(currentTunnelHandle)
|
|
||||||
// }
|
|
||||||
// val wgConfig: String = wireguard_conf!!.toWgUserspaceString()
|
|
||||||
// val builder = Builder()
|
|
||||||
// setupBuilder(wireguard_conf, builder)
|
|
||||||
// builder.setSession("mvpn0")
|
|
||||||
// builder.establish().use { tun ->
|
|
||||||
// if (tun == null)return
|
|
||||||
// Log.i(tag, "Go backend " + wgVersion())
|
|
||||||
// currentTunnelHandle = wgTurnOn("mvpn0", tun.detachFd(), wgConfig)
|
|
||||||
// }
|
|
||||||
// if (currentTunnelHandle < 0) {
|
|
||||||
// Log.e(tag, "Activation Error Code -> $currentTunnelHandle")
|
|
||||||
// isUp = false
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// protect(wgGetSocketV4(currentTunnelHandle))
|
|
||||||
// protect(wgGetSocketV6(currentTunnelHandle))
|
|
||||||
// mConfig = json
|
|
||||||
// isUp = true
|
|
||||||
|
|
||||||
// // Store the config in case the service gets
|
/**
|
||||||
// // asked boot vpn from the OS
|
* Configures an Android VPN Service Tunnel
|
||||||
// val prefs = Prefs.get(this)
|
* with a given Wireguard Config
|
||||||
// prefs.edit()
|
*/
|
||||||
// .putString("lastConf", json.toString())
|
private fun setupBuilder(config: Config, builder: Builder) {
|
||||||
// .apply()
|
// Setup Split tunnel
|
||||||
|
for (excludedApplication in config.`interface`.excludedApplications)
|
||||||
|
builder.addDisallowedApplication(excludedApplication)
|
||||||
|
|
||||||
// NotificationUtil.show(this) // Go foreground
|
// Device IP
|
||||||
|
for (addr in config.`interface`.addresses) builder.addAddress(addr.address, addr.mask)
|
||||||
|
// DNS
|
||||||
startOpenVpn()
|
for (addr in config.`interface`.dnsServers) builder.addDnsServer(addr.hostAddress)
|
||||||
|
// Add All routes the VPN may route tos
|
||||||
return 1//localTunnel
|
for (peer in config.peers) {
|
||||||
|
for (addr in peer.allowedIps) {
|
||||||
}
|
builder.addRoute(addr.address, addr.mask)
|
||||||
|
|
||||||
fun establish(): ParcelFileDescriptor? {
|
|
||||||
return mbuilder.establish()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setMtu(mtu: Int) {
|
|
||||||
Log.v(tag, "setMtu()" + mtu)
|
|
||||||
mbuilder.setMtu(mtu)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addAddress(ip: String, len: Int){
|
|
||||||
Log.v(tag, "addAddress()" + ip + " " + len)
|
|
||||||
mbuilder.addAddress(ip, len)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addRoute(ip: String, len: Int){
|
|
||||||
Log.v(tag, "addRoute()" + ip + " " + len)
|
|
||||||
mbuilder.addRoute(ip, len)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addDNS(ip: String){
|
|
||||||
mbuilder.addDnsServer(ip)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun turnOff() {
|
|
||||||
Log.v(tag, "Try to disable tunnel")
|
|
||||||
wgTurnOff(currentTunnelHandle)
|
|
||||||
currentTunnelHandle = -1
|
|
||||||
stopForeground(false)
|
|
||||||
isUp = false
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures an Android VPN Service Tunnel
|
|
||||||
* with a given Wireguard Config
|
|
||||||
*/
|
|
||||||
private fun setupBuilder(config: Config, builder: Builder) {
|
|
||||||
// Setup Split tunnel
|
|
||||||
for (excludedApplication in config.`interface`.excludedApplications)
|
|
||||||
builder.addDisallowedApplication(excludedApplication)
|
|
||||||
|
|
||||||
// Device IP
|
|
||||||
for (addr in config.`interface`.addresses) builder.addAddress(addr.address, addr.mask)
|
|
||||||
// DNS
|
|
||||||
for (addr in config.`interface`.dnsServers) builder.addDnsServer(addr.hostAddress)
|
|
||||||
// Add All routes the VPN may route tos
|
|
||||||
for (peer in config.peers) {
|
|
||||||
for (addr in peer.allowedIps) {
|
|
||||||
builder.addRoute(addr.address, addr.mask)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
builder.allowFamily(OsConstants.AF_INET)
|
|
||||||
builder.allowFamily(OsConstants.AF_INET6)
|
|
||||||
builder.setMtu(config.`interface`.mtu.orElse(1280))
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) builder.setMetered(false)
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) setUnderlyingNetworks(null)
|
|
||||||
|
|
||||||
builder.setBlocking(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets config value for {key} from the Current
|
|
||||||
* running Wireguard tunnel
|
|
||||||
*/
|
|
||||||
private fun getConfigValue(key: String): String? {
|
|
||||||
if (!isUp) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
val config = wgGetConfig(currentTunnelHandle) ?: return null
|
|
||||||
val lines = config.split("\n")
|
|
||||||
for (line in lines) {
|
|
||||||
val parts = line.split("=")
|
|
||||||
val k = parts.first()
|
|
||||||
val value = parts.last()
|
|
||||||
if (key == k) {
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a Wireguard [Config] from a [json] string -
|
|
||||||
* The [json] will be created in AndroidVpnProtocol.cpp
|
|
||||||
*/
|
|
||||||
private fun buildWireugardConfig(obj: JSONObject): Config {
|
|
||||||
val confBuilder = Config.Builder()
|
|
||||||
val jServer = obj.getJSONObject("server")
|
|
||||||
val peerBuilder = Peer.Builder()
|
|
||||||
val ep =
|
|
||||||
InetEndpoint.parse(jServer.getString("ipv4AddrIn") + ":" + jServer.getString("port"))
|
|
||||||
peerBuilder.setEndpoint(ep)
|
|
||||||
peerBuilder.setPublicKey(Key.fromBase64(jServer.getString("publicKey")))
|
|
||||||
|
|
||||||
val jAllowedIPList = obj.getJSONArray("allowedIPs")
|
|
||||||
if (jAllowedIPList.length() == 0) {
|
|
||||||
val internet = InetNetwork.parse("0.0.0.0/0") // aka The whole internet.
|
|
||||||
peerBuilder.addAllowedIp(internet)
|
|
||||||
} else {
|
|
||||||
(0 until jAllowedIPList.length()).toList().forEach {
|
|
||||||
val network = InetNetwork.parse(jAllowedIPList.getString(it))
|
|
||||||
peerBuilder.addAllowedIp(network)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
builder.allowFamily(OsConstants.AF_INET)
|
||||||
|
builder.allowFamily(OsConstants.AF_INET6)
|
||||||
|
builder.setMtu(config.`interface`.mtu.orElse(1280))
|
||||||
|
|
||||||
confBuilder.addPeer(peerBuilder.build())
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) builder.setMetered(false)
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) setUnderlyingNetworks(null)
|
||||||
|
|
||||||
val privateKey = obj.getJSONObject("keys").getString("privateKey")
|
builder.setBlocking(true)
|
||||||
val jDevice = obj.getJSONObject("device")
|
|
||||||
|
|
||||||
val ifaceBuilder = Interface.Builder()
|
|
||||||
ifaceBuilder.parsePrivateKey(privateKey)
|
|
||||||
ifaceBuilder.addAddress(InetNetwork.parse(jDevice.getString("ipv4Address")))
|
|
||||||
ifaceBuilder.addAddress(InetNetwork.parse(jDevice.getString("ipv6Address")))
|
|
||||||
ifaceBuilder.addDnsServer(InetNetwork.parse(obj.getString("dns")).address)
|
|
||||||
val jExcludedApplication = obj.getJSONArray("excludedApps")
|
|
||||||
(0 until jExcludedApplication.length()).toList().forEach {
|
|
||||||
val appName = jExcludedApplication.get(it).toString()
|
|
||||||
ifaceBuilder.excludeApplication(appName)
|
|
||||||
}
|
|
||||||
confBuilder.setInterface(ifaceBuilder.build())
|
|
||||||
return confBuilder.build()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
private fun startOpenVpn() {
|
* Gets config value for {key} from the Current
|
||||||
Thread ({
|
* running Wireguard tunnel
|
||||||
mOpenVPNThreadv3?.run()
|
*/
|
||||||
}).start()
|
private fun getConfigValue(key: String): String? {
|
||||||
Log.i(tag, "OpenVPNThreadv3 start")
|
if (!isUp) {
|
||||||
isUp = true
|
return null
|
||||||
}
|
}
|
||||||
|
val config = wgGetConfig(currentTunnelHandle) ?: return null
|
||||||
|
val lines = config.split("\n")
|
||||||
|
for (line in lines) {
|
||||||
|
val parts = line.split("=")
|
||||||
|
val k = parts.first()
|
||||||
|
val value = parts.last()
|
||||||
|
if (key == k) {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
/**
|
||||||
@JvmStatic
|
* Create a Wireguard [Config] from a [json] string -
|
||||||
fun startService(c: Context) {
|
* The [json] will be created in AndroidVpnProtocol.cpp
|
||||||
c.applicationContext.startService(
|
*/
|
||||||
Intent(c.applicationContext, VPNService::class.java).apply {
|
private fun buildWireugardConfig(obj: JSONObject): Config {
|
||||||
putExtra("startOnly", true)
|
val confBuilder = Config.Builder()
|
||||||
}
|
val jServer = obj.getJSONObject("server")
|
||||||
)
|
val peerBuilder = Peer.Builder()
|
||||||
|
val ep =
|
||||||
|
InetEndpoint.parse(jServer.getString("ipv4AddrIn") + ":" + jServer.getString("port"))
|
||||||
|
peerBuilder.setEndpoint(ep)
|
||||||
|
peerBuilder.setPublicKey(Key.fromBase64(jServer.getString("publicKey")))
|
||||||
|
|
||||||
|
val jAllowedIPList = obj.getJSONArray("allowedIPs")
|
||||||
|
if (jAllowedIPList.length() == 0) {
|
||||||
|
val internet = InetNetwork.parse("0.0.0.0/0") // aka The whole internet.
|
||||||
|
peerBuilder.addAllowedIp(internet)
|
||||||
|
} else {
|
||||||
|
(0 until jAllowedIPList.length()).toList().forEach {
|
||||||
|
val network = InetNetwork.parse(jAllowedIPList.getString(it))
|
||||||
|
peerBuilder.addAllowedIp(network)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
private external fun wgGetConfig(handle: Int): String?
|
|
||||||
@JvmStatic
|
|
||||||
private external fun wgGetSocketV4(handle: Int): Int
|
|
||||||
@JvmStatic
|
|
||||||
private external fun wgGetSocketV6(handle: Int): Int
|
|
||||||
@JvmStatic
|
|
||||||
private external fun wgTurnOff(handle: Int)
|
|
||||||
@JvmStatic
|
|
||||||
private external fun wgTurnOn(ifName: String, tunFd: Int, settings: String): Int
|
|
||||||
@JvmStatic
|
|
||||||
private external fun wgVersion(): String?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
confBuilder.addPeer(peerBuilder.build())
|
||||||
|
|
||||||
|
val privateKey = obj.getJSONObject("keys").getString("privateKey")
|
||||||
|
val jDevice = obj.getJSONObject("device")
|
||||||
|
|
||||||
|
val ifaceBuilder = Interface.Builder()
|
||||||
|
ifaceBuilder.parsePrivateKey(privateKey)
|
||||||
|
ifaceBuilder.addAddress(InetNetwork.parse(jDevice.getString("ipv4Address")))
|
||||||
|
ifaceBuilder.addAddress(InetNetwork.parse(jDevice.getString("ipv6Address")))
|
||||||
|
ifaceBuilder.addDnsServer(InetNetwork.parse(obj.getString("dns")).address)
|
||||||
|
val jExcludedApplication = obj.getJSONArray("excludedApps")
|
||||||
|
(0 until jExcludedApplication.length()).toList().forEach {
|
||||||
|
val appName = jExcludedApplication.get(it).toString()
|
||||||
|
ifaceBuilder.excludeApplication(appName)
|
||||||
|
}
|
||||||
|
confBuilder.setInterface(ifaceBuilder.build())
|
||||||
|
return confBuilder.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getVpnConfig(): JSONObject {
|
||||||
|
return mConfig!!
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startOpenVpn() {
|
||||||
|
Thread ({
|
||||||
|
mOpenVPNThreadv3?.run()
|
||||||
|
}).start()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun openvpnConnected(){
|
||||||
|
isUp = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun startWireGuard(){
|
||||||
|
val wireguard_conf = buildWireugardConfig(mConfig!!)
|
||||||
|
if (currentTunnelHandle != -1) {
|
||||||
|
Log.e(tag, "Tunnel already up")
|
||||||
|
// Turn the tunnel down because this might be a switch
|
||||||
|
wgTurnOff(currentTunnelHandle)
|
||||||
|
}
|
||||||
|
val wgConfig: String = wireguard_conf!!.toWgUserspaceString()
|
||||||
|
val builder = Builder()
|
||||||
|
setupBuilder(wireguard_conf, builder)
|
||||||
|
builder.setSession("mvpn0")
|
||||||
|
builder.establish().use { tun ->
|
||||||
|
if (tun == null)return
|
||||||
|
Log.i(tag, "Go backend " + wgVersion())
|
||||||
|
currentTunnelHandle = wgTurnOn("mvpn0", tun.detachFd(), wgConfig)
|
||||||
|
}
|
||||||
|
if (currentTunnelHandle < 0) {
|
||||||
|
Log.e(tag, "Activation Error Code -> $currentTunnelHandle")
|
||||||
|
isUp = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
protect(wgGetSocketV4(currentTunnelHandle))
|
||||||
|
protect(wgGetSocketV6(currentTunnelHandle))
|
||||||
|
isUp = true
|
||||||
|
|
||||||
|
// Store the config in case the service gets
|
||||||
|
// asked boot vpn from the OS
|
||||||
|
val prefs = Prefs.get(this)
|
||||||
|
prefs.edit()
|
||||||
|
.putString("lastConf", mConfig.toString())
|
||||||
|
.apply()
|
||||||
|
|
||||||
|
NotificationUtil.show(this) // Go foreground
|
||||||
|
}
|
||||||
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
|
fun startService(c: Context) {
|
||||||
|
c.applicationContext.startService(
|
||||||
|
Intent(c.applicationContext, VPNService::class.java).apply {
|
||||||
|
putExtra("startOnly", true)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
private external fun wgGetConfig(handle: Int): String?
|
||||||
|
@JvmStatic
|
||||||
|
private external fun wgGetSocketV4(handle: Int): Int
|
||||||
|
@JvmStatic
|
||||||
|
private external fun wgGetSocketV6(handle: Int): Int
|
||||||
|
@JvmStatic
|
||||||
|
private external fun wgTurnOff(handle: Int)
|
||||||
|
@JvmStatic
|
||||||
|
private external fun wgTurnOn(ifName: String, tunFd: Int, settings: String): Int
|
||||||
|
@JvmStatic
|
||||||
|
private external fun wgVersion(): String?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@ class VPNServiceBinder(service: VPNService) : Binder() {
|
||||||
const val resumeActivate = 7
|
const val resumeActivate = 7
|
||||||
const val setNotificationText = 8
|
const val setNotificationText = 8
|
||||||
const val setFallBackNotification = 9
|
const val setFallBackNotification = 9
|
||||||
const val myLog = 10
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -54,7 +53,6 @@ class VPNServiceBinder(service: VPNService) : Binder() {
|
||||||
val buffer = data.createByteArray()
|
val buffer = data.createByteArray()
|
||||||
val json = buffer?.let { String(it) }
|
val json = buffer?.let { String(it) }
|
||||||
val config = JSONObject(json)
|
val config = JSONObject(json)
|
||||||
Log.v(tag, "config: " + config.toString())
|
|
||||||
Log.v(tag, "Stored new Tunnel config in Service")
|
Log.v(tag, "Stored new Tunnel config in Service")
|
||||||
|
|
||||||
if (!mService.checkPermissions()) {
|
if (!mService.checkPermissions()) {
|
||||||
|
|
@ -65,109 +63,108 @@ class VPNServiceBinder(service: VPNService) : Binder() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
this.mService.turnOn(config)
|
this.mService.turnOn(config)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(tag, "An Error occurred while enabling the VPN: ${e.localizedMessage}")
|
||||||
|
dispatchEvent(EVENTS.activationError, e.localizedMessage)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
ACTIONS.resumeActivate -> {
|
||||||
|
// [data] is empty
|
||||||
|
// Activate the current tunnel
|
||||||
|
try {
|
||||||
|
mResumeConfig?.let { this.mService.turnOn(it) }
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(tag, "An Error occurred while enabling the VPN: ${e.localizedMessage}")
|
Log.e(tag, "An Error occurred while enabling the VPN: ${e.localizedMessage}")
|
||||||
dispatchEvent(EVENTS.activationError, e.localizedMessage)
|
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
ACTIONS.resumeActivate -> {
|
ACTIONS.deactivate -> {
|
||||||
// [data] is empty
|
// [data] here is empty
|
||||||
// Activate the current tunnel
|
this.mService.turnOff()
|
||||||
try {
|
return true
|
||||||
mResumeConfig?.let { this.mService.turnOn(it) }
|
}
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e(tag, "An Error occurred while enabling the VPN: ${e.localizedMessage}")
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
ACTIONS.deactivate -> {
|
ACTIONS.registerEventListener -> {
|
||||||
// [data] here is empty
|
// [data] contains the Binder that we need to dispatch the Events
|
||||||
this.mService.turnOff()
|
val binder = data.readStrongBinder()
|
||||||
return true
|
mListener = binder
|
||||||
}
|
val obj = JSONObject()
|
||||||
|
obj.put("connected", mService.isUp)
|
||||||
|
obj.put("time", mService.connectionTime)
|
||||||
|
dispatchEvent(EVENTS.init, obj.toString())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
ACTIONS.registerEventListener -> {
|
ACTIONS.requestStatistic -> {
|
||||||
// [data] contains the Binder that we need to dispatch the Events
|
dispatchEvent(EVENTS.statisticUpdate, mService.status.toString())
|
||||||
val binder = data.readStrongBinder()
|
return true
|
||||||
mListener = binder
|
}
|
||||||
val obj = JSONObject()
|
|
||||||
obj.put("connected", mService.isUp)
|
|
||||||
obj.put("time", mService.connectionTime)
|
|
||||||
dispatchEvent(EVENTS.init, obj.toString())
|
|
||||||
Log.i(tag, "ACTIONS.registerEventListener")
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
ACTIONS.requestStatistic -> {
|
ACTIONS.requestGetLog -> {
|
||||||
dispatchEvent(EVENTS.statisticUpdate, mService.status.toString())
|
// Grabs all the Logs and dispatch new Log Event
|
||||||
return true
|
dispatchEvent(EVENTS.backendLogs, Log.getContent())
|
||||||
}
|
return true
|
||||||
|
}
|
||||||
|
ACTIONS.requestCleanupLog -> {
|
||||||
|
Log.clearFile()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
ACTIONS.setNotificationText -> {
|
||||||
|
NotificationUtil.update(data)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
ACTIONS.setFallBackNotification -> {
|
||||||
|
NotificationUtil.saveFallBackMessage(data, mService)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
IBinder.LAST_CALL_TRANSACTION -> {
|
||||||
|
Log.e(tag, "The OS Requested to shut down the VPN")
|
||||||
|
this.mService.turnOff()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
ACTIONS.requestGetLog -> {
|
else -> {
|
||||||
// Grabs all the Logs and dispatch new Log Event
|
Log.e(tag, "Received invalid bind request \t Code -> $code")
|
||||||
dispatchEvent(EVENTS.backendLogs, Log.getContent())
|
// If we're hitting this there is probably something wrong in the client.
|
||||||
return true
|
return false
|
||||||
}
|
}
|
||||||
ACTIONS.requestCleanupLog -> {
|
}
|
||||||
Log.clearFile()
|
return false
|
||||||
return true
|
}
|
||||||
}
|
|
||||||
ACTIONS.setNotificationText -> {
|
|
||||||
NotificationUtil.update(data)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
ACTIONS.setFallBackNotification -> {
|
|
||||||
// NotificationUtil.saveFallBackMessage(data, mService)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
IBinder.LAST_CALL_TRANSACTION -> {
|
|
||||||
Log.e(tag, "The OS Requested to shut down the VPN")
|
|
||||||
this.mService.turnOff()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> {
|
/**
|
||||||
Log.e(tag, "Received invalid bind request \t Code -> $code")
|
* Dispatches an Event to all registered Binders
|
||||||
// If we're hitting this there is probably something wrong in the client.
|
* [code] the Event that happened - see [EVENTS]
|
||||||
return false
|
* To register an Eventhandler use [onTransact] with
|
||||||
|
* [ACTIONS.registerEventListener]
|
||||||
|
*/
|
||||||
|
fun dispatchEvent(code: Int, payload: String?) {
|
||||||
|
try {
|
||||||
|
mListener?.let {
|
||||||
|
if (it.isBinderAlive) {
|
||||||
|
val data = Parcel.obtain()
|
||||||
|
data.writeByteArray(payload?.toByteArray(charset("UTF-8")))
|
||||||
|
it.transact(code, data, Parcel.obtain(), 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
} catch (e: DeadObjectException) {
|
||||||
|
// If the QT Process is killed (not just inactive)
|
||||||
|
// we cant access isBinderAlive, so nothing to do here.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dispatches an Event to all registered Binders
|
* The codes we Are Using in case of [dispatchEvent]
|
||||||
* [code] the Event that happened - see [EVENTS]
|
|
||||||
* To register an Eventhandler use [onTransact] with
|
|
||||||
* [ACTIONS.registerEventListener]
|
|
||||||
*/
|
*/
|
||||||
fun dispatchEvent(code: Int, payload: String?) {
|
object EVENTS {
|
||||||
try {
|
const val init = 0
|
||||||
mListener?.let {
|
const val connected = 1
|
||||||
if (it.isBinderAlive) {
|
const val disconnected = 2
|
||||||
val data = Parcel.obtain()
|
const val statisticUpdate = 3
|
||||||
data.writeByteArray(payload?.toByteArray(charset("UTF-8")))
|
const val backendLogs = 4
|
||||||
it.transact(code, data, Parcel.obtain(), 0)
|
const val activationError = 5
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: DeadObjectException) {
|
|
||||||
// If the QT Process is killed (not just inactive)
|
|
||||||
// we cant access isBinderAlive, so nothing to do here.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The codes we Are Using in case of [dispatchEvent]
|
|
||||||
*/
|
|
||||||
object EVENTS {
|
|
||||||
const val init = 0
|
|
||||||
const val connected = 1
|
|
||||||
const val disconnected = 2
|
|
||||||
const val statisticUpdate = 3
|
|
||||||
const val backendLogs = 4
|
|
||||||
const val activationError = 5
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ class VPNPermissionHelper : android.net.VpnService() {
|
||||||
* is present and prompting if not.
|
* is present and prompting if not.
|
||||||
*/
|
*/
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
|
Log.i(tag, "onStartCommand")
|
||||||
val intent = prepare(this.applicationContext)
|
val intent = prepare(this.applicationContext)
|
||||||
Log.i(tag, "VPNPermissionHelper onStartCommand")
|
|
||||||
if (intent != null) {
|
if (intent != null) {
|
||||||
startActivityForResult(intent)
|
startActivityForResult(intent)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,7 @@ int main(int argc, char *argv[])
|
||||||
qRegisterMetaType<Protocol>("Protocol");
|
qRegisterMetaType<Protocol>("Protocol");
|
||||||
qRegisterMetaType<ServiceType>("ServiceType");
|
qRegisterMetaType<ServiceType>("ServiceType");
|
||||||
qRegisterMetaType<Page>("Page");
|
qRegisterMetaType<Page>("Page");
|
||||||
|
qRegisterMetaType<VpnProtocol::ConnectionState>("ConnectionState");
|
||||||
|
|
||||||
qRegisterMetaType<PageProtocolLogicBase *>("PageProtocolLogicBase *");
|
qRegisterMetaType<PageProtocolLogicBase *>("PageProtocolLogicBase *");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ AndroidVpnProtocol* AndroidVpnProtocol::instance() {
|
||||||
return s_instance;
|
return s_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidVpnProtocol::initialize()
|
bool AndroidVpnProtocol::initialize()
|
||||||
{
|
{
|
||||||
qDebug() << "Initializing";
|
qDebug() << "Initializing";
|
||||||
|
|
||||||
|
|
@ -81,9 +81,12 @@ void AndroidVpnProtocol::initialize()
|
||||||
"(Landroid/content/Context;)V", appContext.object());
|
"(Landroid/content/Context;)V", appContext.object());
|
||||||
|
|
||||||
// Start the VPN Service (if not yet) and Bind to it
|
// Start the VPN Service (if not yet) and Bind to it
|
||||||
QtAndroid::bindService(
|
const bool bindResult = QtAndroid::bindService(
|
||||||
QAndroidIntent(appContext.object(), "org.amnezia.vpn.VPNService"),
|
QAndroidIntent(appContext.object(), "org.amnezia.vpn.VPNService"),
|
||||||
*this, QtAndroid::BindFlag::AutoCreate);
|
*this, QtAndroid::BindFlag::AutoCreate);
|
||||||
|
qDebug() << "Binding to the service..." << bindResult;
|
||||||
|
|
||||||
|
return bindResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorCode AndroidVpnProtocol::start()
|
ErrorCode AndroidVpnProtocol::start()
|
||||||
|
|
@ -91,45 +94,49 @@ ErrorCode AndroidVpnProtocol::start()
|
||||||
|
|
||||||
qDebug() << "Prompting for VPN permission";
|
qDebug() << "Prompting for VPN permission";
|
||||||
auto appContext = QtAndroid::androidActivity().callObjectMethod(
|
auto appContext = QtAndroid::androidActivity().callObjectMethod(
|
||||||
"getApplicationContext", "()Landroid/content/Context;");
|
"getApplicationContext", "()Landroid/content/Context;");
|
||||||
QAndroidJniObject::callStaticMethod<void>(
|
QAndroidJniObject::callStaticMethod<void>(
|
||||||
PERMISSIONHELPER_CLASS, "startService", "(Landroid/content/Context;)V",
|
PERMISSIONHELPER_CLASS, "startService", "(Landroid/content/Context;)V",
|
||||||
appContext.object());
|
appContext.object());
|
||||||
|
|
||||||
|
|
||||||
// QJsonObject jServer;
|
// QJsonObject jServer;
|
||||||
// jServer["ipv4AddrIn"] = server.ipv4AddrIn();
|
// jServer["ipv4AddrIn"] = server.ipv4AddrIn();
|
||||||
// jServer["ipv4Gateway"] = server.ipv4Gateway();
|
// jServer["ipv4Gateway"] = server.ipv4Gateway();
|
||||||
// jServer["ipv6AddrIn"] = server.ipv6AddrIn();
|
// jServer["ipv6AddrIn"] = server.ipv6AddrIn();
|
||||||
// jServer["ipv6Gateway"] = server.ipv6Gateway();
|
// jServer["ipv6Gateway"] = server.ipv6Gateway();
|
||||||
// jServer["publicKey"] = server.publicKey();
|
// jServer["publicKey"] = server.publicKey();
|
||||||
// jServer["port"] = (int)server.choosePort();
|
// jServer["port"] = (int)server.choosePort();
|
||||||
|
|
||||||
// QJsonArray allowedIPs;
|
// QJsonArray allowedIPs;
|
||||||
// foreach (auto item, allowedIPAddressRanges) {
|
// foreach (auto item, allowedIPAddressRanges) {
|
||||||
// QJsonValue val;
|
// QJsonValue val;
|
||||||
// val = item.toString();
|
// val = item.toString();
|
||||||
// allowedIPs.append(val);
|
// allowedIPs.append(val);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// QJsonArray excludedApps;
|
// QJsonArray excludedApps;
|
||||||
// foreach (auto appID, vpnDisabledApps) {
|
// foreach (auto appID, vpnDisabledApps) {
|
||||||
// excludedApps.append(QJsonValue(appID));
|
// excludedApps.append(QJsonValue(appID));
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// QJsonObject args;
|
// QJsonObject args;
|
||||||
// args["device"] = jDevice;
|
// args["device"] = jDevice;
|
||||||
// args["keys"] = jKeys;
|
// args["keys"] = jKeys;
|
||||||
// args["server"] = jServer;
|
// args["server"] = jServer;
|
||||||
// args["reason"] = (int)reason;
|
// args["reason"] = (int)reason;
|
||||||
// args["allowedIPs"] = allowedIPs;
|
// args["allowedIPs"] = allowedIPs;
|
||||||
// args["excludedApps"] = excludedApps;
|
// args["excludedApps"] = excludedApps;
|
||||||
// args["dns"] = dns.toString();
|
// args["dns"] = dns.toString();
|
||||||
|
|
||||||
QAndroidParcel sendData;
|
QAndroidParcel sendData;
|
||||||
sendData.writeData(QJsonDocument(m_rawConfig).toJson());
|
sendData.writeData(QJsonDocument(m_rawConfig).toJson());
|
||||||
m_serviceBinder.transact(ACTION_ACTIVATE, sendData, nullptr);
|
bool activateResult = false;
|
||||||
return NoError;
|
while (!activateResult){
|
||||||
|
activateResult = m_serviceBinder.transact(ACTION_ACTIVATE, sendData, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return activateResult ? NoError : UnknownError;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Activates the tunnel that is currently set
|
// Activates the tunnel that is currently set
|
||||||
|
|
@ -212,7 +219,7 @@ void AndroidVpnProtocol::cleanupBackendLogs() {
|
||||||
|
|
||||||
void AndroidVpnProtocol::onServiceConnected(
|
void AndroidVpnProtocol::onServiceConnected(
|
||||||
const QString& name, const QAndroidBinder& serviceBinder) {
|
const QString& name, const QAndroidBinder& serviceBinder) {
|
||||||
qDebug() << "Server connected";
|
qDebug() << "Server " + name + " connected";
|
||||||
|
|
||||||
Q_UNUSED(name);
|
Q_UNUSED(name);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ public:
|
||||||
|
|
||||||
virtual ~AndroidVpnProtocol() override = default;
|
virtual ~AndroidVpnProtocol() override = default;
|
||||||
|
|
||||||
void initialize();
|
bool initialize();
|
||||||
|
|
||||||
virtual ErrorCode start() override;
|
virtual ErrorCode start() override;
|
||||||
virtual void stop() override;
|
virtual void stop() override;
|
||||||
|
|
|
||||||
|
|
@ -232,7 +232,6 @@ ErrorCode VpnConnection::connectToVpn(int serverIndex,
|
||||||
m_vpnProtocol.reset();
|
m_vpnProtocol.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ErrorCode e = ErrorCode::NoError;
|
ErrorCode e = ErrorCode::NoError;
|
||||||
m_vpnConfiguration = createVpnConfiguration(serverIndex, credentials, container, containerConfig);
|
m_vpnConfiguration = createVpnConfiguration(serverIndex, credentials, container, containerConfig);
|
||||||
if (e) {
|
if (e) {
|
||||||
|
|
@ -252,8 +251,12 @@ ErrorCode VpnConnection::connectToVpn(int serverIndex,
|
||||||
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
AndroidVpnProtocol *androidVpnProtocol = new AndroidVpnProtocol(Protocol::OpenVpn, m_vpnConfiguration);
|
Protocol proto = ContainerProps::defaultProtocol(container);
|
||||||
androidVpnProtocol->initialize();
|
AndroidVpnProtocol *androidVpnProtocol = new AndroidVpnProtocol(proto, m_vpnConfiguration);
|
||||||
|
if (!androidVpnProtocol->initialize()) {
|
||||||
|
qDebug() << QString("Init failed") ;
|
||||||
|
return UnknownError;
|
||||||
|
}
|
||||||
m_vpnProtocol.reset(androidVpnProtocol);
|
m_vpnProtocol.reset(androidVpnProtocol);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue