将connection区分为内网和外网两种,根据mode进行选择

This commit is contained in:
free will
2021-08-11 10:51:53 +08:00
parent 1f28ce4859
commit e77fff0271
7 changed files with 755 additions and 774 deletions
@@ -5,8 +5,10 @@ package com.pkusz.min_vpn_client;
public class GlobalSetting {
// public static boolean openBiometric = false;
// 控制与VPNServer的对称加密通信方法,true表示使用sm4,false表示使用AES
// 控制内网中与VPNServer的对称加密通信方法,true表示使用sm4,false表示使用AES
public static boolean isSM4 = true;
// 控制外网中与VPNServer的对称加密通信方法,暂时只支持SM4
public static boolean isSM4InExternal = true;
// 是否开启VPN服务器信息同步
public static boolean openSyncVPNInfo = false;
@@ -0,0 +1,12 @@
package com.pkusz.min_vpn_client.model;
/*
* @Author: Wang Feng
* @Description: 存储路由配置的信息
* 最最基础的字段:mtu addr dns
* @Version: 1.0.0
* @Date: 10:04 2021/8/11
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
*/
public class VpnServiceInfo {
}
@@ -0,0 +1,29 @@
package com.pkusz.min_vpn_client.services;
/*
* @Author: Wang Feng
* @Description:
* @Version: 1.0.0
* @Date: 9:04 2021/8/11
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
*/
import android.app.PendingIntent;
import android.os.ParcelFileDescriptor;
public interface MINVpnConnection extends Runnable{
// 三种回调函数接口的声明
interface OnEstablishListener {
void onEstablish(ParcelFileDescriptor tunInterface);
}
interface OnConnectFailedListener {
void onFailed();
}
interface OnTimeoutFailedListener {
void onTimeout();
}
// 共有方法
void setConfigureIntent(PendingIntent intent);
void setOnEstablishListener(OnEstablishListener listener);
void setOnConnectFailedListener(OnConnectFailedListener listener);
void setOnTimeoutFailedListener(OnTimeoutFailedListener listener);
}
File diff suppressed because it is too large Load Diff
@@ -49,7 +49,7 @@ import util.ByteHelper;
import static java.nio.charset.StandardCharsets.US_ASCII;
public class MINVpnInnerConnection implements Runnable{
public class MINVpnInnerConnection implements MINVpnConnection{
private static long interestSeq = 0; // 兴趣包序号
private String handshakeResponse = null; // 握手应答
private ParcelFileDescriptor mParcelFileDescriptor = null; // 读出写入流
@@ -91,16 +91,6 @@ public class MINVpnInnerConnection implements Runnable{
private OnEstablishListener mOnEstablishListener;
private OnConnectFailedListener mOnConnectFailedListener;
private OnTimeoutFailedListener mOnTimeoutFailedListener;
// 三种回调函数接口的声明
public interface OnEstablishListener {
void onEstablish(ParcelFileDescriptor tunInterface);
}
public interface OnConnectFailedListener {
void onFailed();
}
public interface OnTimeoutFailedListener {
void onTimeout();
}
/**
* 构造函数
@@ -141,30 +131,6 @@ public class MINVpnInnerConnection implements Runnable{
+" , len: "+realSecret.length);
}
// 测试AES
// System.out.println("!!!密钥:"+mSharedSecretString);
// byte[] res=AESHelperForConnection.encryptWithAES(mSharedSecretString,
// "ilovecodingilovecodingilovecodingilovecodingilovecodingilovecodingilovecodingilovecoding" +
// "ilovecodingilovecodingsuygdygyegdw".getBytes(StandardCharsets.UTF_8));
// System.out.println("!!!: "+res);
// String raw=AESHelperForConnection.decryptWithAES(mSharedSecretString,res);
// System.out.println("!!!raw: "+raw);
// 测试SM4
// try {
// byte[] enc= Android_SM4.encrypt_ECB_Padding("1234567812345678".getBytes(StandardCharsets.UTF_8),
// "wefree".getBytes(StandardCharsets.UTF_8));
// System.out.println("enc: "+Arrays.toString(enc));
// System.out.println("enc: "+new String(enc));
// byte[] dec= Android_SM4.decrypt_ECB_Padding("1234567812345678".getBytes(StandardCharsets.UTF_8),
// enc);
// System.out.println("dec: "+Arrays.toString(dec));
// System.out.println("dec: "+new String(dec));
// } catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchProviderException
// | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException e) {
// e.printStackTrace();
// }
// 代理地址(?)
if(!TextUtils.isEmpty(proxyHostName)) {
mProxyHostName = proxyHostName;
@@ -179,6 +145,7 @@ public class MINVpnInnerConnection implements Runnable{
}
// Intend进行activity之间的消息传递
@Override
public void setConfigureIntent(PendingIntent intent) {
mConfigureIntent = intent;
}
@@ -204,7 +171,7 @@ public class MINVpnInnerConnection implements Runnable{
}
// 2. VPN握手,交换信息
boolean flag=handShake(face);
boolean flag=handShake(face,true);
if((this.mParcelFileDescriptor==null)||(!flag)){
LoggerHelper.severe("vpn connection run error: handle shake error");
return;
@@ -217,6 +184,28 @@ public class MINVpnInnerConnection implements Runnable{
startHeartBeatThread(face,500);
}
/**
* 现行版本下,由于外网服务器自己并不分配IP,tun的IP分配仍然由内网服务器做
* @return
*/
@RequiresApi(api = Build.VERSION_CODES.Q)
public String getAllocatedAddressFromInnerServer(){
// 1. 建立一条连接服务器的TCP-LogicFace
LogicFace face=initTCPLogicFace(this.mServerName,this.mServerPort);
if(face==null){
LoggerHelper.severe("vpn connection run error: tcp logic face init error");
return "";
}
// 2. VPN握手,交换信息。握手成功则返回内网服务器分配的IP
boolean flag=handShake(face,false);
if(flag){
return this.allocatedAddress;
}
return "";
}
/**
* 开启心跳包
* @param face
@@ -446,14 +435,15 @@ public class MINVpnInnerConnection implements Runnable{
/**
* VPN握手,交换信息。
* @param face
* @param needConfig 是否需要根据握手信息进行相应路由配置
*/
@RequiresApi(api = Build.VERSION_CODES.Q)
private boolean handShake(LogicFace face){
private boolean handShake(LogicFace face,boolean needConfig){
// 1. 构造兴趣包
// 构造兴趣包负载字段:加密密钥 & 本地前缀
ByteBuffer requestBuf = ByteBuffer.allocate(1024);
byte len= ByteHelper.uint8ToByte(mEncryptedAESSeed.length);
if(!GlobalSetting.isSM4) {
if(!this.isSM4) {
requestBuf.put((byte) 4).put(len).put(mEncryptedAESSeed).put(localFacePrefix.getBytes()).flip();
}else{
requestBuf.put((byte) 1).put(len).put(mEncryptedAESSeed).put(localFacePrefix.getBytes()).flip();
@@ -555,7 +545,9 @@ public class MINVpnInnerConnection implements Runnable{
// 4. 分析服务器的数据包应答,根据其中信息进行本地的路由配置
System.out.println("handshake result : " + this.handshakeResponse);
this.mParcelFileDescriptor = configure(this.handshakeResponse);
if(needConfig) {
this.mParcelFileDescriptor = configure(this.handshakeResponse);
}
return true;
}
@@ -589,8 +581,9 @@ public class MINVpnInnerConnection implements Runnable{
break;
case 'r':
// 服务器配置
// todo: 测试用
if(MINVpnSettingAPI.INSTANCE.getProxyMode() == 2) {
builder.addRoute(fields[1], Integer.parseInt(fields[2]));
// builder.addRoute(fields[1], Integer.parseInt(fields[2]));
}
break;
case 'd':
@@ -608,10 +601,6 @@ public class MINVpnInnerConnection implements Runnable{
if(MINVpnSettingAPI.INSTANCE.getProxyMode() == 0) {
configRoute(builder);
}
// 全局
if(MINVpnSettingAPI.INSTANCE.getProxyMode() == 1) {
builder.addRoute("0.0.0.0",0);
}
// 2. 创建一个接口
final ParcelFileDescriptor vpnInterface;
@@ -1,7 +1,7 @@
package com.pkusz.min_vpn_client.services;
/*
* @Author: Wang Feng
* @Description:
* @Description: 参考安卓项目组给出的ToyVPN
* @Version: 1.0.0
* @Date: 10:52 2021/7/13
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
@@ -58,16 +58,13 @@ public class MINVpnService extends VpnService implements Handler.Callback{
private final AtomicReference<Thread> mConnectingThread = new AtomicReference<>();
private final AtomicReference<Connection> mConnection = new AtomicReference<>();
// vpn 连接
private MINVpnInnerConnection minVpnConnection=null;
// vpn 连接: 内网或外网
private MINVpnConnection minVpnConnection=null;
// connection id
private AtomicInteger mNextConnectionId = new AtomicInteger(1);
// 通信intent
private PendingIntent mConfigureIntent;
// vpn 外网连接 => 支持访问国外网站
// private MINVpnExternalConnection minVpnExternalConnection=null;
@Override
public void onCreate() {
// 使用handler显示消息
@@ -145,7 +142,6 @@ public class MINVpnService extends VpnService implements Handler.Callback{
final String server = MINVpnSettingAPI.INSTANCE.getMirIpAddress();
final int port = MINVpnSettingAPI.INSTANCE.getMirPort();
// 生成消息加密密钥
// final byte[] secret = RSACryptoForConnection.getRandomAESSeed().PlainSeed.getBytes();
final byte[] secret = SM4HelperForConnection.getRandomSeed(); // 获取随机16位长度密钥,用于对称加密
// 权限控制集合(并不知道为啥弄这个,我只是继承了由多人零零散散写、改了一年的客户端代码。)
final boolean allow = false;
@@ -155,20 +151,43 @@ public class MINVpnService extends VpnService implements Handler.Callback{
final String proxyHost = "";
final int proxyPort = 0;
// 默认开启网服务器的连接
minVpnConnection = new MINVpnInnerConnection(
this, mNextConnectionId.getAndIncrement(), server, port, secret,
proxyHost, proxyPort, allow, packages, GlobalSetting.isSM4);
// 对vpn connection进行各种监听设置,并启动执行其run函数
startConnection(minVpnConnection);
// 根据全局变量,判断 是否开启外网服务器的连接
if(GlobalSetting.openFirewall){
// final byte[] secretToExtra = SM4HelperForConnection.getRandomSeed(); // 获取随机16位长度密钥,用于对称加密
// minVpnExternalConnection = new MINVpnExternalConnection(
// this,mNextConnectionId.getAndIncrement(),
// MINVpnSettingAPI.INSTANCE.getOneExtranetVpnServerInfo(),secretToExtra,
// proxyHost,proxyPort,allow,packages,GlobalSetting.isSM4);
// 根据mode,判断是否开启网服务器的连接
// 2表示内网,1表示外网
System.out.println("当前VPN模式: "+MINVpnSettingAPI.INSTANCE.getProxyMode());
if(MINVpnSettingAPI.INSTANCE.getProxyMode()==2){
// 开启内网服务器的连接
minVpnConnection = new MINVpnInnerConnection(
this, mNextConnectionId.getAndIncrement(), server, port, secret,
proxyHost, proxyPort, allow, packages, GlobalSetting.isSM4);
// 对vpn connection进行各种监听设置,并启动执行其run函数
startConnection(minVpnConnection);
}else if(MINVpnSettingAPI.INSTANCE.getProxyMode()==1){
// 通过与内网服务器握手,获取tun网卡的IP地址
MINVpnInnerConnection innerConnection = new MINVpnInnerConnection(
this, mNextConnectionId.getAndIncrement(), server, port, secret,
proxyHost, proxyPort, allow, packages, GlobalSetting.isSM4);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
innerConnection.run();
}
String allocateIP;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
allocateIP=innerConnection.getAllocatedAddressFromInnerServer();
System.out.println("已经为外网访问获取到IP: "+allocateIP);
}else {
System.out.println("外网访问获取到IP失败");
return;
}
if(allocateIP.length()<=0){
System.out.println("外网访问获取到IP失败");
return;
}
// 开启外网服务器的连接
minVpnConnection = new MINVpnExternalConnection(
this,mNextConnectionId.getAndIncrement(),
MINVpnSettingAPI.INSTANCE.getOneExtranetVpnServerInfo(),secret,
proxyHost,proxyPort,allow,packages,GlobalSetting.isSM4InExternal,allocateIP);
// 对vpn connection进行各种监听设置,并启动执行其run函数
startConnection(minVpnConnection);
}
}
@@ -176,7 +195,7 @@ public class MINVpnService extends VpnService implements Handler.Callback{
* 启动一条vpn连接
* @param connection
*/
private void startConnection(final MINVpnInnerConnection connection) {
private void startConnection(final MINVpnConnection connection) {
System.out.println("begin start connection...");
// 将vpn连接放入一个线程里
final Thread thread = new Thread(connection, "MINVpnThread");
@@ -210,6 +229,7 @@ public class MINVpnService extends VpnService implements Handler.Callback{
* 关掉vpn连接
*/
private void disconnect(){
System.out.println("收到了关掉连接的消息...");
mHandler.sendEmptyMessage(R.string.disconnected);
setConnectingThread(null);
setConnection(null);