[Android開發思路]打造你的VPN app:Android VpnManager開發思路心得
2022, Apr 21
前言
在這篇文章中,
我們將分享開發自己研究的Android VPN 應用的思路,
不論您是新手還是有經驗的開發者,
這些筆記都將提供實用的指引,
希望能對您有所幫助。
前期可以考慮的問題
思考要怎麼實作,所以先研究了原生有哪些VPN加密連線方式
- 這邊看了原生Android AOSP source code內有的VPN連線加密方式:
- PPTP
- L2TP/IPSec PSK
- IPSec Xauth Psk
- IPSec IKEv2 PSK
- L2TP/IPSec RSA
- IPSec Xauth RSA
- IPSec 混合 RSA
- IPSec IKEv2 RSA
若是有個需求為,要實作VPN連線加密模式功能,則:
- 官方原生提供的方法有:VpnManager、
VpnService
我研究後發現:
- 如果用
VpnManager
,僅提供部分Vpn連線模式,且高版本(api 30上)才有提供 - 如果用
VpnService
,僅提供基本的一些設定,無開放連線模式的接口給上層使用
- 如果用
VpnManager
,需api 30才能使用,且只有開放部分protocol- 另外有看到google issue tracker的網站中,
有其他開發者有類似問題,並詢問官方是否能開放下層的連線模式
給上層使用,
官方人員回覆 後續有望開放:點此查看
表示也有其他人有類似需求,但目前官方暫無開發
- 另外有看到google issue tracker的網站中,
- 之前提到官方只支援部分加密方式,其他的就得靠自己實作或串接第三方的lib啦!
這張圖列出了官方支援的三種加密方式:IPSec IKEv2 PSK、IPSec IKEv2 RSA、IPSec User Pass。
VPN實作的思路參考
- 若使用
官方提供
的方法來實作,可以:'連接類型'
:透過VpnManager (API level 30以上)的provisionVpnProfile方法設定PlatformVpnProfile
- 官方定義一個新的類別 PlatformVpnProfile
- 若搭配AOSP看的話,官方是提供這個類讓你
設定部分連線procotol
最後到下層的Service時會幫你轉換成真正在Service用的VpnProfile類 - 也就是VpnManager的
line 335
: provisionVpnProfile(@NonNull PlatformVpnProfile profile) 最後是用 toVpnProfile()幫你把PlatformVpnProfile
轉為VpnProfile
- 若搭配AOSP看的話,官方是提供這個類讓你
- 其中Ikev2VpnProfile.Builder 可以設定Ikev2相關連線設置,這個類其實就是實作
PlatformVpnProfile
讓你去設定開放的protocol模式
- 官方定義一個新的類別 PlatformVpnProfile
'vpn設置相關'
: 通過VpnService,在建立本地tunnel的時候加入VpnService.Builder()
- 官方 VpnService架構圖
- 此方法設定連線時的Tunnel,官方僅提供如下方example所示的方法 給開發者使用
- 雖然AOSP內有提供相關protocol連線,但是
尚未開放
給上層使用, 故若需要相關protocol進行連線,則需自行開發
- example :
/*** Android level 14 up ***/ val builder = VpnService.Builder() val localTunnel = builder .setSession('VPN名字') .addAddress('服務器', 'prefix length') .addRoute('轉發路由', 'prefix length') .addDnsServer('DNS服務器') .addSearchDomain('DNS 搜索域') .establish()
- 官方 VpnService架構圖
透過其他或第三方方案來實作Vpn app
若官方提供開放的方法,還無法滿足需求,則可考慮:
- AnyConnect:第三方VPN供應商,目前看到第三方廠商的VPN服務
- AnyConnect官方文件提到有提供 TLS、DTLS、IPsec IKEv2 等等的protocol
- 另一份AnyConnect文件提到要使用IPsec IKEv2 連接 需要Cisco Adaptive Security Appliance 8.4以上
- 使用此選項的話,需要與廠商接洽,才能得知如何開發、細節等
- 此表下方有個表解釋每個平台支持的Tunneling
- AnyConnect 4.10 release note,文件較下面有提到Android版本上有部分相容性問題:
- 像是Android 5.0、6.0 省電模式會與該服務衝突
- Split DNS 無法在Android4.4 或 三星 5.x Android 設備運作
(供參考)
看到網路上有一解法去設定VpnProfile,透過反射framework內的方法直接使用:Create VPN profile on Android- 但在Android 9.0以上此法已被修正,故推測有些較早期的手機可能使用這種方法 (若目標裝置在這之前,還能考慮)
- 修正公告
(供參考)
第三方 openVpn 有提供Android開源- 說明文件提到支援
SSL/TLS
協議(僅支援該協議)
- 加入openVpn到android專案方法:點此
- ics-openvpn FAQ也有提到三星5.0手機問題
- 說明文件提到支援
其餘知識點
-
透過app開啟自定義VpnService時,在Android 8.0 以上service運作新增後台執行限制
-
追蹤android-10.0.0_r1 aosp內的 VpnService.java 其
line:176~179
使用了 IConnectivityManager.aidl,但目前在framework層找不到實作aidl的痕跡, 故推測有可能是放在binder之類的,若要了解它怎麼實作的,可能要再研究底層code -
追蹤 Android 12 aosp內的 VpnService.Java,其
line:178~181
使用的aidl改成IVpnManager.aidl, source code內有另一個檔案為VpnManagerService.Java其中
line:293
的provisionVpnProfile(VpnProfile profile,...)
這個method要求提供一個變數VpnProfile點進去看VpnProfile的
line:97
得知其預設連線方案為:public int type = TYPE_PPTP
且看到VpnProfile可設定的連線模式有:
不過這些目前僅在aosp內有支援這些連線模式
且因為沒有開放出來,所以無法寫在app內直接使用
總結來說
一來非開發者只能從手機設定裡那邊修改
二來開發者要自行實作只能從aosp那邊下手