android4.4.2 VPN路由配置過程分析,ppp0預設路由設定過程分析
阿新 • • 發佈:2019-01-04
Android VPN啟動後會up一個ppp0的網路裝置,此網路裝置就是應用翻牆要發向的裝置。目前我的理解是,看下面的路由表,ppp0有一個預設路由所有的資料都先通過預設路由傳送到ppp0上,然後通過WIFI裝置的預設路由傳送出去。
//路由表:
[email protected]_sp7715ga:/ # busybox route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default * 0.0.0.0 U 0 0 0 ppp0
default 192.168.43.1 0.0.0.0 UG 207 0 0 wlan0
192.168.2.10 * 255.255.255.255 UH 0 0 0 ppp0
192.168.43.0 * 255.255.255.0 U 207 0 0 wlan0
//pppd啟動,有本地IP和一個遠端IP,所有的包都通過PPP協議將資料包發到遠端伺服器上,由於第三方應用的資料,所有的DNS請求都要傳送到8.8.8.8
05-01 10:44:01.434 I/mtpd ( 1493): Starting pppd (pppox = 12)
05-01 10:44:01.494 I/pppd ( 1495): Using PPPoX (socket = 12)
05-01 10:44:01.504 D/pppd ( 1495): using channel 1
05-01 10:44:01.524 I/pppd ( 1495): Using interface ppp0
05-01 10:44:01.524 I/pppd ( 1495): Connect: ppp0 <-->
05-01 10:44:05.174 I/pppd ( 1495): MPPE 128-bit stateless compression enabled
05-01 10:44:06.784 I/pppd ( 1495): local IP address 192.168.2.16
05-01 10:44:06.784 I/pppd ( 1495): remote IP address 192.168.2.10
05-01 10:44:06.784 I/pppd ( 1495): primary DNS address 209.11.240.36
05-01 10:44:06.784 I/pppd ( 1495): secondary DNS address 8.8.8.8
追蹤預設路由的新增過程,見LOG
05-01 10:43:24.434 D/WirelessSettings( 754): onPreferenceTreeClick: preference=VPN
05-01 10:43:58.014 I/Vpn ( 554): Switched from [Legacy VPN] to [Legacy VPN]
05-01 10:44:06.814 D/VPN ( 554): mConfig.routes is null. add route parameters[2]=0.0.0.0/0
05-01 10:44:07.074 D/VPN ( 554): set the routes:[0.0.0.0/0 -> 0.0.0.0]
05-01 10:44:07.074 D/VPN ( 554): setRoutes route=0.0.0.0/0 -> 0.0.0.0
//程式碼解析,並添加里部分LOG
packages\apps\settings\src\com\android\settings\vpn2\VpnSettings.java
onClick(DialogInterface dialog, int button) --> connect(profile) -->mService.startLegacyVpn(profile)
frameworks\base\services\java\com\android\server\ConnectivityService.java
startLegacyVpn(VpnProfile profile) --> mVpns.get(user).startLegacyVpn(profile, mKeyStore, egress)
frameworks\base\services\java\com\android\server\connectivity\Vpn.java
startLegacyVpn(VpnProfile profile, KeyStore keyStore, LinkProperties egress) --> startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd) --> mLegacyVpnRunner = new LegacyVpnRunner(config, racoon, mtpd); mLegacyVpnRunner.start(); // Start a new LegacyVpnRunner and we are done!
frameworks\base\services\java\com\android\server\connectivity\Vpn.java
private class LegacyVpnRunner extends Thread
run() --> execute() {
// Set the routes if they are not set in the config.
if (mConfig.routes == null || mConfig.routes.isEmpty()) {
Slog.d("VPN", "mConfig.routes is null. add route parameters[2]=" + parameters[2]);
mConfig.addLegacyRoutes(parameters[2]);
}
}
//新增VPN的DNS 8.8.8.8
// Set the DNS servers if they are not set in the config.
if (mConfig.dnsServers == null || mConfig.dnsServers.size() == 0) {
String dnsServers = parameters[3].trim();
if (!dnsServers.isEmpty()) {
mConfig.dnsServers = Arrays.asList(dnsServers.split(" "));
}
}
//parameters哪裡來的?
frameworks\base\services\java\com\android\server\connectivity\Vpn.java
// Now we are connected. Read and parse the new state.
String[] parameters = FileUtils.readTextFile(state, 0, null).split("\n", -1); //state 檔案哪裡來的?
if (parameters.length != 6) {
throw new IllegalStateException("Cannot parse the state");
}
//LegacyVpnRunner執行緒執行run->execute()
frameworks\base\services\java\com\android\server\connectivity\Vpn.java
private class LegacyVpnRunner extends Thread {
private void execute() {
// Catch all exceptions so we can clean up few things.
boolean initFinished = false;
try {
// Initialize the timer.
checkpoint(false);
// Wait for the daemons to stop.
for (String daemon : mDaemons) {
while (!SystemService.isStopped(daemon)) {
checkpoint(true);
}
}
// Clear the previous state.
File state = new File("/data/misc/vpn/state");
state.delete();
if (state.exists()) {
throw new IllegalStateException("Cannot delete the state");
}
new File("/data/misc/vpn/abort").delete();
initFinished = true;
//省略一部分程式碼
......
......
......
// Wait for the daemons to create the new state. //deamons建立的檔案,那他們是誰?
while (!state.exists()) {
// Check if a running daemon is dead.
for (int i = 0; i < mDaemons.length; ++i) {
String daemon = mDaemons[i];
if (mArguments[i] != null && !SystemService.isRunning(daemon)) {
throw new IllegalStateException(daemon + " is dead");
}
}
checkpoint(true);
}
//原來deamons是他們"racoon", "mtpd"
frameworks\base\services\java\com\android\server\connectivity\Vpn.java
public LegacyVpnRunner(VpnConfig config, String[] racoon, String[] mtpd) {
super(TAG);
mConfig = config;
mDaemons = new String[] {"racoon", "mtpd"};
//我們看看這個檔案state
[email protected]_sp7715ga:/data/misc/vpn # cat state
ppp0
192.168.2.16/32
0.0.0.0/0
209.11.240.36 8.8.8.8
//上接execute()的
frameworks\base\core\java\com\android\internal\net\VpnConfig.java
public void addLegacyRoutes(String routesStr) {
if (routesStr.trim().equals("")) {
return;
}
String[] routes = routesStr.trim().split(" ");
for (String route : routes) {
//each route is ip/prefix
String[] split = route.split("/");
RouteInfo info = new RouteInfo(new LinkAddress
(InetAddress.parseNumericAddress(split[0]), Integer.parseInt(split[1])), null);
this.routes.add(info); //新增到List routes中。
}
}
frameworks\base\services\java\com\android\server\connectivity\Vpn.java
long token = Binder.clearCallingIdentity();
try {
mCallback.setMarkedForwarding(mConfig.interfaze);
Slog.d("VPN", "set the routes:" + mConfig.routes.toString());
mCallback.setRoutes(mConfig.interfaze, mConfig.routes); //將List routes的路由都新增到路由表中
} finally {
Binder.restoreCallingIdentity(token);
}
//最終還是由ConnectivityService的介面來新增ppp0的預設路由,這也是開頭我們說的地方。
frameworks\base\services\java\com\android\server\ConnectivityService.java
public class VpnCallback {
public void setRoutes(String interfaze, List<RouteInfo> routes) {
for (RouteInfo route : routes) {
try {
//@bug302150 //android4.4.2 vpn就有bug。
//mNetd.setMarkedForwardingRoute(interfaze, route);
Slog.d("VPN", "setRoutes route=" + route);
mNetd.addRoute(interfaze, route);
} catch (RemoteException e) {
}
}
}
//路由表:
[email protected]_sp7715ga:/ # busybox route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default * 0.0.0.0 U 0 0 0 ppp0
default 192.168.43.1 0.0.0.0 UG 207 0 0 wlan0
192.168.2.10 * 255.255.255.255 UH 0 0 0 ppp0
192.168.43.0 * 255.255.255.0 U 207 0 0 wlan0
//pppd啟動,有本地IP和一個遠端IP,所有的包都通過PPP協議將資料包發到遠端伺服器上,由於第三方應用的資料,所有的DNS請求都要傳送到8.8.8.8
05-01 10:44:01.434 I/mtpd ( 1493): Starting pppd (pppox = 12)
05-01 10:44:01.494 I/pppd ( 1495): Using PPPoX (socket = 12)
05-01 10:44:01.504 D/pppd ( 1495): using channel 1
05-01 10:44:01.524 I/pppd ( 1495): Using interface ppp0
05-01 10:44:01.524 I/pppd ( 1495): Connect: ppp0 <-->
05-01 10:44:05.174 I/pppd ( 1495): MPPE 128-bit stateless compression enabled
05-01 10:44:06.784 I/pppd ( 1495): local IP address 192.168.2.16
05-01 10:44:06.784 I/pppd ( 1495): remote IP address 192.168.2.10
05-01 10:44:06.784 I/pppd ( 1495): primary DNS address 209.11.240.36
05-01 10:44:06.784 I/pppd ( 1495): secondary DNS address 8.8.8.8
追蹤預設路由的新增過程,見LOG
05-01 10:43:24.434 D/WirelessSettings( 754): onPreferenceTreeClick: preference=VPN
05-01 10:43:58.014 I/Vpn ( 554): Switched from [Legacy VPN] to [Legacy VPN]
05-01 10:44:06.814 D/VPN ( 554): mConfig.routes is null. add route parameters[2]=0.0.0.0/0
05-01 10:44:07.074 D/VPN ( 554): set the routes:[0.0.0.0/0 -> 0.0.0.0]
05-01 10:44:07.074 D/VPN ( 554): setRoutes route=0.0.0.0/0 -> 0.0.0.0
//程式碼解析,並添加里部分LOG
packages\apps\settings\src\com\android\settings\vpn2\VpnSettings.java
onClick(DialogInterface dialog, int button) --> connect(profile) -->mService.startLegacyVpn(profile)
frameworks\base\services\java\com\android\server\ConnectivityService.java
startLegacyVpn(VpnProfile profile) --> mVpns.get(user).startLegacyVpn(profile, mKeyStore, egress)
frameworks\base\services\java\com\android\server\connectivity\Vpn.java
startLegacyVpn(VpnProfile profile, KeyStore keyStore, LinkProperties egress) --> startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd) --> mLegacyVpnRunner = new LegacyVpnRunner(config, racoon, mtpd); mLegacyVpnRunner.start(); // Start a new LegacyVpnRunner and we are done!
frameworks\base\services\java\com\android\server\connectivity\Vpn.java
private class LegacyVpnRunner extends Thread
run() --> execute() {
// Set the routes if they are not set in the config.
if (mConfig.routes == null || mConfig.routes.isEmpty()) {
Slog.d("VPN", "mConfig.routes is null. add route parameters[2]=" + parameters[2]);
mConfig.addLegacyRoutes(parameters[2]);
}
}
//新增VPN的DNS 8.8.8.8
// Set the DNS servers if they are not set in the config.
if (mConfig.dnsServers == null || mConfig.dnsServers.size() == 0) {
String dnsServers = parameters[3].trim();
if (!dnsServers.isEmpty()) {
mConfig.dnsServers = Arrays.asList(dnsServers.split(" "));
}
}
//parameters哪裡來的?
frameworks\base\services\java\com\android\server\connectivity\Vpn.java
// Now we are connected. Read and parse the new state.
String[] parameters = FileUtils.readTextFile(state, 0, null).split("\n", -1); //state 檔案哪裡來的?
if (parameters.length != 6) {
throw new IllegalStateException("Cannot parse the state");
}
//LegacyVpnRunner執行緒執行run->execute()
frameworks\base\services\java\com\android\server\connectivity\Vpn.java
private class LegacyVpnRunner extends Thread {
private void execute() {
// Catch all exceptions so we can clean up few things.
boolean initFinished = false;
try {
// Initialize the timer.
checkpoint(false);
// Wait for the daemons to stop.
for (String daemon : mDaemons) {
while (!SystemService.isStopped(daemon)) {
checkpoint(true);
}
}
// Clear the previous state.
File state = new File("/data/misc/vpn/state");
state.delete();
if (state.exists()) {
throw new IllegalStateException("Cannot delete the state");
}
new File("/data/misc/vpn/abort").delete();
initFinished = true;
//省略一部分程式碼
......
......
......
// Wait for the daemons to create the new state. //deamons建立的檔案,那他們是誰?
while (!state.exists()) {
// Check if a running daemon is dead.
for (int i = 0; i < mDaemons.length; ++i) {
String daemon = mDaemons[i];
if (mArguments[i] != null && !SystemService.isRunning(daemon)) {
throw new IllegalStateException(daemon + " is dead");
}
}
checkpoint(true);
}
//原來deamons是他們"racoon", "mtpd"
frameworks\base\services\java\com\android\server\connectivity\Vpn.java
public LegacyVpnRunner(VpnConfig config, String[] racoon, String[] mtpd) {
super(TAG);
mConfig = config;
mDaemons = new String[] {"racoon", "mtpd"};
//我們看看這個檔案state
ppp0
192.168.2.16/32
0.0.0.0/0
209.11.240.36 8.8.8.8
//上接execute()的
frameworks\base\core\java\com\android\internal\net\VpnConfig.java
public void addLegacyRoutes(String routesStr) {
if (routesStr.trim().equals("")) {
return;
}
String[] routes = routesStr.trim().split(" ");
for (String route : routes) {
//each route is ip/prefix
String[] split = route.split("/");
RouteInfo info = new RouteInfo(new LinkAddress
(InetAddress.parseNumericAddress(split[0]), Integer.parseInt(split[1])), null);
this.routes.add(info); //新增到List routes中。
}
}
frameworks\base\services\java\com\android\server\connectivity\Vpn.java
long token = Binder.clearCallingIdentity();
try {
mCallback.setMarkedForwarding(mConfig.interfaze);
Slog.d("VPN", "set the routes:" + mConfig.routes.toString());
mCallback.setRoutes(mConfig.interfaze, mConfig.routes); //將List routes的路由都新增到路由表中
} finally {
Binder.restoreCallingIdentity(token);
}
//最終還是由ConnectivityService的介面來新增ppp0的預設路由,這也是開頭我們說的地方。
frameworks\base\services\java\com\android\server\ConnectivityService.java
public class VpnCallback {
public void setRoutes(String interfaze, List<RouteInfo> routes) {
for (RouteInfo route : routes) {
try {
//@bug302150 //android4.4.2 vpn就有bug。
//mNetd.setMarkedForwardingRoute(interfaze, route);
Slog.d("VPN", "setRoutes route=" + route);
mNetd.addRoute(interfaze, route);
} catch (RemoteException e) {
}
}
}