mirror of
https://gitee.com/willfree/min-vpn-client_v2.git
synced 2026-10-04 19:42:00 +08:00
外访方案第一步地址转换,已实现从TUN网卡中读取ip包,并抽取相关信息。正在实现修改ip地址并写回TUN网卡中。
This commit is contained in:
1 parent
c4b04300e8
commit
9368d21267
5 files changed
+350
-21
No files matched your search
@@ -73,7 +73,7 @@ public class LoginActivity extends MINVpnBaseActivity<LoginActivityPresenter>
|
||||
private ClearAbleEditText etPassword;
|
||||
private CircularProgressButton export_identity;
|
||||
private CircularProgressButton import_identity;
|
||||
private CircularProgressButton test;
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
@@ -91,7 +91,7 @@ public class LoginActivity extends MINVpnBaseActivity<LoginActivityPresenter>
|
||||
etPassword=findViewById(R.id.etPassword);
|
||||
export_identity=findViewById(R.id.export_identity);
|
||||
import_identity=findViewById(R.id.import_identity);
|
||||
test=findViewById(R.id.test);
|
||||
|
||||
|
||||
initView();
|
||||
}
|
||||
@@ -232,11 +232,6 @@ public class LoginActivity extends MINVpnBaseActivity<LoginActivityPresenter>
|
||||
mPresenter.login(loginRequest);
|
||||
});
|
||||
|
||||
//测试地址转换方案
|
||||
test.setOnClickListener(v->{
|
||||
|
||||
});
|
||||
|
||||
// 监听键盘是否弹起
|
||||
ActivityExtensionsKt.listenKeyboardVisible(this,(isOpen)->{
|
||||
if(isOpen){
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.pkusz.min_vpn_client.activity.main.MainActivity;
|
||||
import com.pkusz.min_vpn_client.model.MINVpnSettingAPI;
|
||||
import com.pkusz.min_vpn_client.model.event.ConnectEvent;
|
||||
import com.pkusz.min_vpn_client.model.event.TimeoutEvent;
|
||||
import com.pkusz.min_vpn_client.services.minsocks.MINVpnLBConnection;
|
||||
import com.pkusz.min_vpn_client.utils.SM4HelperForConnection;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
@@ -156,10 +157,14 @@ public class MINVpnService extends VpnService implements Handler.Callback{
|
||||
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函数
|
||||
// minVpnConnection = new MINVpnInnerConnection(
|
||||
// this, mNextConnectionId.getAndIncrement(), server, port, secret,
|
||||
// proxyHost, proxyPort, allow, packages, GlobalSetting.isSM4);
|
||||
// // 对vpn connection进行各种监听设置,并启动执行其run函数
|
||||
// startConnection(minVpnConnection);
|
||||
//test plan
|
||||
minVpnConnection=new MINVpnLBConnection(this,proxyHost,proxyPort,
|
||||
allow,mNextConnectionId.getAndIncrement(),packages,server,port);
|
||||
startConnection(minVpnConnection);
|
||||
}else if((MINVpnSettingAPI.INSTANCE.getProxyMode()==1)
|
||||
&&(GlobalSetting.openFirewall)){
|
||||
|
||||
@@ -0,0 +1,322 @@
|
||||
package com.pkusz.min_vpn_client.services.minsocks;
|
||||
/*
|
||||
* @Author: Wang Feng
|
||||
* @Description:
|
||||
* @Version: 1.0.0
|
||||
* @Date: 21:28 2021/8/19
|
||||
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
||||
*/
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.ProxyInfo;
|
||||
import android.net.VpnService;
|
||||
import android.os.Build;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.pkusz.min_vpn_client.services.MINVpnConnection;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
|
||||
import common.LoggerHelper;
|
||||
import util.ByteHelper;
|
||||
|
||||
public class MINVpnLBConnection implements MINVpnConnection {
|
||||
|
||||
// 最大包长度
|
||||
private static final int MAX_PACKET_SIZE = Short.MAX_VALUE;
|
||||
private boolean stop = false; // 标记本次连接是否停止
|
||||
private final VpnService mService;
|
||||
// tun网卡的IP地址
|
||||
private String allocatedAddress;
|
||||
private final int mConnectionId;
|
||||
// 权限控制
|
||||
private final boolean mAllow;
|
||||
private final Set<String> mPackages;
|
||||
// 代理地址 todo:??
|
||||
private String mProxyHostName;
|
||||
private int mProxyHostPort;
|
||||
// 服务器地址、密钥
|
||||
private final String mServerName;
|
||||
private final int mServerPort;
|
||||
// 待决Intent、回调函数(建立连接成功;建立连接失败;长时间不操作的超时回调)
|
||||
private PendingIntent mConfigureIntent;
|
||||
private OnEstablishListener mOnEstablishListener;
|
||||
private OnConnectFailedListener mOnConnectFailedListener;
|
||||
private OnTimeoutFailedListener mOnTimeoutFailedListener;
|
||||
|
||||
//临时存储ip包
|
||||
private ByteBuffer temp_buff=ByteBuffer.allocate(MAX_PACKET_SIZE);
|
||||
private int length_of_ip_packet=0;
|
||||
public MINVpnLBConnection(VpnService mService, final String proxyHostName, final int proxyHostPort,
|
||||
boolean allow,final int connectionId,
|
||||
final Set<String> packages,final String serverName, final int serverPort) {
|
||||
|
||||
this.mService = mService;
|
||||
mConnectionId=connectionId;
|
||||
this.allocatedAddress="10.254.0.2";
|
||||
|
||||
// 代理地址(?)
|
||||
if(!TextUtils.isEmpty(proxyHostName)) {
|
||||
mProxyHostName = proxyHostName;
|
||||
}
|
||||
if(proxyHostPort>0) {
|
||||
mProxyHostPort = proxyHostPort;
|
||||
}
|
||||
// 服务器地址
|
||||
mServerName=serverName;
|
||||
mServerPort=serverPort;
|
||||
|
||||
// 权限控制
|
||||
mAllow=allow;
|
||||
mPackages=packages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConfigureIntent(PendingIntent intent) {
|
||||
mConfigureIntent = intent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnEstablishListener(OnEstablishListener listener) {
|
||||
mOnEstablishListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnConnectFailedListener(OnConnectFailedListener listener) {
|
||||
mOnConnectFailedListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnTimeoutFailedListener(OnTimeoutFailedListener listener) {
|
||||
mOnTimeoutFailedListener = listener;
|
||||
}
|
||||
|
||||
// 不用初始化face,不用握手,不用一切与服务器的通信
|
||||
@RequiresApi(api = Build.VERSION_CODES.Q)
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println("进入测试");
|
||||
// 第一步,配置路由,得到tun读写数据接口(请抄configure()函数)
|
||||
//1.1配置路由
|
||||
VpnService.Builder builder = mService.new Builder();
|
||||
builder.setMtu(8000);
|
||||
builder.addAddress(allocatedAddress,24);
|
||||
builder.addRoute("10.255.0.3",32);
|
||||
builder.addDnsServer("114.114.114.114");
|
||||
// 1.2创建一个接口
|
||||
final ParcelFileDescriptor vpnInterface;
|
||||
// 1.2.1 添加没有权限的目录(copy旧项目的,不知道这个目录指的哪个玩意儿)
|
||||
try {
|
||||
builder.addDisallowedApplication("com.example.androidvpn2");
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// 1.2.2 添加传递进来的有权限或没权限的应用目录
|
||||
for (String packageName : mPackages) {
|
||||
try {
|
||||
if (mAllow) {
|
||||
builder.addAllowedApplication(packageName);
|
||||
} else {
|
||||
builder.addDisallowedApplication(packageName);
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
LoggerHelper.warning(getTag()+ " Package not available: " + packageName+ e);
|
||||
}
|
||||
}
|
||||
// 1.2.3 设置server和proxy的地址,以及intent
|
||||
builder.setSession(mServerName).setConfigureIntent(mConfigureIntent);
|
||||
if (!TextUtils.isEmpty(mProxyHostName)) {
|
||||
builder.setHttpProxy(ProxyInfo.buildDirectProxy(mProxyHostName, mProxyHostPort));
|
||||
}
|
||||
// 1.2.4 根据前面配置的builder创建一个vpn句柄
|
||||
synchronized (mService) {
|
||||
vpnInterface = builder.establish();
|
||||
if (mOnEstablishListener != null) {
|
||||
mOnEstablishListener.onEstablish(vpnInterface);
|
||||
}
|
||||
}
|
||||
LoggerHelper.finer(getTag()+ " New interface: " + vpnInterface + " (" + "全局路由" + ")");
|
||||
// 第二步,从ParcelFileDescriptor读出IP包,read() => 判断目的地址
|
||||
FileInputStream inputStream=new FileInputStream(
|
||||
vpnInterface.getFileDescriptor());
|
||||
FileOutputStream outputStream=new FileOutputStream(
|
||||
vpnInterface.getFileDescriptor());
|
||||
// 2.1-------------- 线程1:从tun网卡读出网络包,并往服务器发 -----------------
|
||||
//从tun网卡中读取到的源ip包
|
||||
ByteBuffer ip_packet_read_from_tun = ByteBuffer.allocate(MAX_PACKET_SIZE);
|
||||
//网络地址转换后的ip包
|
||||
ByteBuffer ip_NAT_packet=ByteBuffer.allocate(MAX_PACKET_SIZE);
|
||||
|
||||
Thread readFromTun = new Thread(() -> {
|
||||
while(!this.stop){
|
||||
ip_packet_read_from_tun.clear();
|
||||
int readLen = 0;
|
||||
// 1. 读取tun网卡数据,放入ip_packet_read_from_tun
|
||||
try {
|
||||
readLen = inputStream.read(ip_packet_read_from_tun.array(), 0, MAX_PACKET_SIZE);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
System.out.println("从tun网卡中读取内容失败");
|
||||
}
|
||||
int[] ip_address_unsignedInt_first=new int[8];
|
||||
if(readLen>0){
|
||||
System.out.println("A new packet,");
|
||||
System.out.println("read from tun , readLen ="+readLen);
|
||||
ip_packet_read_from_tun.position(0);
|
||||
ip_packet_read_from_tun.limit(readLen);
|
||||
|
||||
// String binaryString = Integer.toBinaryString(first);
|
||||
byte[] ipPackageData = new byte[readLen];
|
||||
System.arraycopy(ip_packet_read_from_tun.array(), 0, ipPackageData, 0, readLen);
|
||||
System.out.println("ip packet's content is: " + Arrays.toString(ipPackageData));
|
||||
|
||||
//读取源ip: [0]-[3],10.254.0.2 , 目的ip: [4]-[7],10.255.0.3
|
||||
for(int i=12;i<20;i++){
|
||||
ip_address_unsignedInt_first[i-12]=Byte.toUnsignedInt(ipPackageData[i]);
|
||||
}
|
||||
for(int i=0;i<8;i++){
|
||||
if(i==0)
|
||||
System.out.print("source ip is "+ip_address_unsignedInt_first[i]);
|
||||
else if(i>=1&&i<=3)
|
||||
System.out.print("."+ip_address_unsignedInt_first[i]);
|
||||
else if(i==4)
|
||||
System.out.print("\ndestination ip is "+ip_address_unsignedInt_first[i]);
|
||||
else
|
||||
System.out.print("."+ip_address_unsignedInt_first[i]);
|
||||
}
|
||||
System.out.print("\n");
|
||||
|
||||
// 跳转到第3步
|
||||
//第3.2步,如果目的地址是10.254.0.1,用face发出去【不用实现,打印即可】
|
||||
if(ip_address_unsignedInt_first[4]==10 && ip_address_unsignedInt_first[5]==254
|
||||
&& ip_address_unsignedInt_first[6]==0 && ip_address_unsignedInt_first[7]==1){
|
||||
System.out.println("目的地址为10.254.0.1,由face向httpsVPN发出");
|
||||
}
|
||||
// 第3.1步,如果目的地址不是10.254.0.1,先将IP包的源端口号和目的IP端口号存入表iptables,
|
||||
// 然后做NAT转换,做完NAT转换的IP包写入tun(通过ParcelFileDescriptor) write()
|
||||
else{
|
||||
System.out.println("目的地址不是10.254.0.1,进行地址转换");
|
||||
ip_NAT_packet.clear();
|
||||
|
||||
//更换ip包中目的地址为要转换的地址
|
||||
byte[] address_to_NAT_byte=new byte[4];
|
||||
int[] address_to_NAT_unsignedINT={192,168,3,2};
|
||||
for(int i=0;i<4;i++){
|
||||
address_to_NAT_byte[i]=ByteHelper.uint8ToByte(address_to_NAT_unsignedINT[i]);
|
||||
//System.out.print(address_to_NAT_byte[i]+" ");
|
||||
ipPackageData[i+16]=address_to_NAT_byte[i];
|
||||
}
|
||||
//搜一下怎么换ip地址,还要更换包里面其他的内容吗
|
||||
ip_NAT_packet.put(ipPackageData);
|
||||
|
||||
//从buffer中读取转换后的ip包
|
||||
// byte[] ipdata_changing= ip_NAT_packet.array();
|
||||
// System.out.println("the content of ip packet after changing is: " + Arrays.toString(ipdata_changing));
|
||||
// //读取源ip: [12]-[15] , 目的ip: [16]-[19],192.168.3.2
|
||||
// int[] ip_address_unsignedInt_changing=new int[8];
|
||||
// //将ip转化为unsigned int
|
||||
// for(int i=12;i<20;i++){
|
||||
// ip_address_unsignedInt_changing[i-12]=Byte.toUnsignedInt(ipdata_changing[i]);
|
||||
// }
|
||||
// for(int i=0;i<8;i++){
|
||||
// if(i==0)
|
||||
// System.out.print("source ip is "+ip_address_unsignedInt_changing[i]);
|
||||
// else if(i>=1&&i<=3)
|
||||
// System.out.print("."+ip_address_unsignedInt_changing[i]);
|
||||
// else if(i==4)
|
||||
// System.out.print("\ndestination ip is "+ip_address_unsignedInt_changing[i]);
|
||||
// else
|
||||
// System.out.print("."+ip_address_unsignedInt_changing[i]);
|
||||
// }
|
||||
// System.out.print("\n");
|
||||
|
||||
try {
|
||||
outputStream.write(ip_NAT_packet.array(), 0, ip_NAT_packet.position());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
System.out.println("将抓转换后的地址写入tun网卡失败");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
readFromTun.start();
|
||||
|
||||
|
||||
|
||||
// // 第3.1步,如果目的地址不是10.254.0.1,先将IP包的源端口号和目的IP端口号存入表iptables,
|
||||
// // 然后做NAT转换,做完NAT转换的IP包写入tun(通过ParcelFileDescriptor) write()
|
||||
// Thread writeToTun = new Thread(() -> {
|
||||
// while(this.stop){
|
||||
// System.out.println("write thread "+temp_buff.position());
|
||||
// if(temp_buff.position()!=0){
|
||||
// //获取要进行地址转换的ip包
|
||||
// ip_NAT_packet.clear();
|
||||
// byte[] ipPackageData = new byte[length_of_ip_packet];
|
||||
// System.arraycopy(temp_buff.array(), 0, ipPackageData, 0, length_of_ip_packet);
|
||||
// ip_NAT_packet.put(ipPackageData);
|
||||
// temp_buff.clear();
|
||||
//
|
||||
// //print content
|
||||
// byte[] ipdata= ip_NAT_packet.array();
|
||||
// System.out.println("the content of ip packet that need to be changed is: " + Arrays.toString(ipdata));
|
||||
// //读取源ip: [0]-[3],10.254.0.2 , 目的ip: [4]-[7],10.255.0.3
|
||||
// byte[] ip_address_byte=new byte[8];
|
||||
// int[] ip_address_unsignedInt=new int[8];
|
||||
// ip_NAT_packet.position(12);
|
||||
// ip_NAT_packet.get(ip_address_byte);
|
||||
// //将ip转化为unsigned int
|
||||
// System.out.print("source ip is ");
|
||||
// for(int i=0;i<4;i++){
|
||||
// ip_address_unsignedInt[i]=Byte.toUnsignedInt(ip_address_byte[i]);
|
||||
// if(i!=3)
|
||||
// System.out.print(ip_address_unsignedInt[i]+".");
|
||||
// else
|
||||
// System.out.print(ip_address_unsignedInt[i]);
|
||||
// }
|
||||
// System.out.print("\ndestination ip is ");
|
||||
// for(int i=4;i<8;i++){
|
||||
// ip_address_unsignedInt[i]=Byte.toUnsignedInt(ip_address_byte[i]);
|
||||
// if(i!=7)
|
||||
// System.out.print(ip_address_unsignedInt[i]+".");
|
||||
// else
|
||||
// System.out.print(ip_address_unsignedInt[i]);
|
||||
// }
|
||||
// System.out.print("\n");
|
||||
//
|
||||
// //
|
||||
//
|
||||
//
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// writeToTun.start();
|
||||
// 第3.2步,如果目的地址是10.254.0.1,用face发出去【不用实现,打印即可】
|
||||
}
|
||||
|
||||
// 输出提示信息时使用
|
||||
private final String getTag() {
|
||||
return MINVpnLBConnection.class.getSimpleName() + "[" + mConnectionId + "]";
|
||||
}
|
||||
|
||||
private void transfer_ip_packet_from_thread(ByteBuffer ip_packet,int readLen){
|
||||
temp_buff.clear();
|
||||
byte[] ipPackageData = new byte[readLen];
|
||||
System.arraycopy(ip_packet.array(), 0, ipPackageData, 0, readLen);
|
||||
temp_buff.put(ipPackageData);
|
||||
length_of_ip_packet=readLen;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.pkusz.min_vpn_client.services.minsocks;
|
||||
/*
|
||||
* @Author: Wang Feng
|
||||
* @Description:
|
||||
* @Version: 1.0.0
|
||||
* @Date: 21:32 2021/8/19
|
||||
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
||||
*/
|
||||
|
||||
public class socks {
|
||||
// 第一步,启动TCP服务器监听1080
|
||||
|
||||
// 第二步,收到TCP连接之后,查询iptables,发往10.254.0.1(服务器上的tun地址)【也不用实现】
|
||||
// 这里收到TCP连接之后,直接取出源端口号,打印对应的iptable表项 或者全部打印iptables
|
||||
|
||||
}
|
||||
@@ -176,15 +176,6 @@
|
||||
app:layout_constraintTop_toBottomOf="@id/btnLogin"
|
||||
/>
|
||||
|
||||
<br.com.simplepass.loadingbutton.customViews.CircularProgressButton
|
||||
android:id="@+id/test"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="test"
|
||||
android:background="@drawable/button_shape_default"
|
||||
tools:ignore="MissingConstraints"
|
||||
android:textColor="@color/white"
|
||||
tools:layout_editor_absoluteX="43dp"
|
||||
tools:layout_editor_absoluteY="568dp" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
Reference in new issue
Block a user