外访方案第一步地址转换,已实现从TUN网卡中读取ip包,并抽取相关信息。正在实现修改ip地址并写回TUN网卡中。

This commit is contained in:
liubohahaha committed 2021-08-27 19:17:19 +08:00
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
}
+1 -10
View File
@@ -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>