mirror of
https://gitee.com/willfree/min-vpn-client_v2.git
synced 2026-10-04 19:42:00 +08:00
更换目的地址、tcp端口,计算ip包、tcp报文字段中的校验和,并写回tun网卡中。下一步研究tun网卡的流量流向,以及如何、从何读出地址修改后的ip包。
This commit is contained in:
1 parent
9368d21267
commit
de51fdec72
1 file changed
+173
-25
+173
-25
@@ -27,6 +27,7 @@ import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
|
||||
import common.LoggerHelper;
|
||||
import jnr.ffi.annotations.In;
|
||||
import util.ByteHelper;
|
||||
|
||||
public class MINVpnLBConnection implements MINVpnConnection {
|
||||
@@ -111,6 +112,7 @@ public class MINVpnLBConnection implements MINVpnConnection {
|
||||
builder.setMtu(8000);
|
||||
builder.addAddress(allocatedAddress,24);
|
||||
builder.addRoute("10.255.0.3",32);
|
||||
builder.addRoute("192.168.0.0",16);
|
||||
builder.addDnsServer("114.114.114.114");
|
||||
// 1.2创建一个接口
|
||||
final ParcelFileDescriptor vpnInterface;
|
||||
@@ -169,15 +171,67 @@ public class MINVpnLBConnection implements MINVpnConnection {
|
||||
}
|
||||
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);
|
||||
|
||||
try {
|
||||
//System.out.println("after changing, position is"+ip_NAT_packet.position());
|
||||
System.out.println("直接写入,再读出");
|
||||
//outputStream.write(ip_NAT_packet.array(), 0, ip_NAT_packet.position());
|
||||
outputStream.write(ip_packet_read_from_tun.array(), 0, ip_packet_read_from_tun.position());
|
||||
ByteBuffer temp_buffer = ByteBuffer.allocate(MAX_PACKET_SIZE);
|
||||
int temp_readLen=inputStream.read(temp_buffer.array(), 0, MAX_PACKET_SIZE);
|
||||
System.out.println("temp readLen is "+temp_readLen);
|
||||
byte[] tempData = new byte[temp_readLen];
|
||||
System.arraycopy(temp_buffer.array(), 0, tempData, 0, temp_readLen);
|
||||
printHexString("直接从TUN中读:",tempData);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
System.out.println("将抓转换后的地址写入tun网卡失败");
|
||||
}
|
||||
|
||||
// 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));
|
||||
// System.out.println("ip packet's content is: " + Arrays.toString(ipPackageData));
|
||||
|
||||
if(ipPackageData[12]==0 && ipPackageData[13]==0
|
||||
&& ipPackageData[14]==0 && ipPackageData[15]==0){
|
||||
System.out.println("源地址为0.0.0.0,暂时跳过");
|
||||
continue;
|
||||
}
|
||||
|
||||
System.out.println("A new packet,");
|
||||
System.out.println("read from tun , readLen ="+readLen);
|
||||
printHexString("ip packet's content is: ",ipPackageData);
|
||||
|
||||
//ip包的各种信息
|
||||
//ip头部长度,tcp报文长度
|
||||
int ip_head_length=(ipPackageData[0] & 0x0F)*4;
|
||||
int tcp_length=readLen-ip_head_length;
|
||||
//源端口、目的端口
|
||||
byte[] source_port=new byte[2];
|
||||
source_port[0]=ipPackageData[ip_head_length];
|
||||
source_port[1]=ipPackageData[ip_head_length+1];
|
||||
byte[] destination_port=new byte[2];
|
||||
destination_port[0]=ipPackageData[ip_head_length+2];
|
||||
destination_port[1]=ipPackageData[ip_head_length+3];
|
||||
|
||||
|
||||
byte[] test_ipPackageData = new byte[readLen];
|
||||
System.arraycopy(ip_packet_read_from_tun.array(), 0, test_ipPackageData, 0, readLen);
|
||||
ByteBuffer test_ip_packet=ByteBuffer.allocate(MAX_PACKET_SIZE);
|
||||
test_ip_packet.put(test_ipPackageData);
|
||||
|
||||
//calculate the head checksum
|
||||
// short ip_checksum=computeChecksum(ipPackageData,20);
|
||||
// System.out.println("the checksum of ip packet is "+ Integer.toHexString(Short.toUnsignedInt(ip_checksum)));
|
||||
// System.out.println("the checksum(unsigned int) of ip packet is "+ Short.toUnsignedInt(ip_checksum));
|
||||
// System.out.println("the checksum(short) of ip packet is "+ ip_checksum);
|
||||
// 将byte数组按16进制输出
|
||||
// byte[] test=new byte[2];
|
||||
// test=ByteHelper.uint16ToByteArray(Short.toUnsignedInt(ip_checksum));
|
||||
// System.out.println("the checksum(hex) of ip packet is "+Integer.toHexString(test[0] & 0xFF)+" "+Integer.toHexString(test[1] & 0xFF));
|
||||
|
||||
//读取源ip: [0]-[3],10.254.0.2 , 目的ip: [4]-[7],10.255.0.3
|
||||
for(int i=12;i<20;i++){
|
||||
@@ -188,12 +242,14 @@ public class MINVpnLBConnection implements MINVpnConnection {
|
||||
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)
|
||||
else if(i==4){
|
||||
System.out.print(" source tcp port is "+ByteHelper.new_byteArrayToInt(source_port));
|
||||
System.out.print("\ndestination ip is "+ip_address_unsignedInt_first[i]);
|
||||
}
|
||||
else
|
||||
System.out.print("."+ip_address_unsignedInt_first[i]);
|
||||
}
|
||||
System.out.print("\n");
|
||||
System.out.print(" destination tcp port is "+ByteHelper.new_byteArrayToInt(destination_port)+"\n");
|
||||
|
||||
// 跳转到第3步
|
||||
//第3.2步,如果目的地址是10.254.0.1,用face发出去【不用实现,打印即可】
|
||||
@@ -206,22 +262,66 @@ public class MINVpnLBConnection implements MINVpnConnection {
|
||||
else{
|
||||
System.out.println("目的地址不是10.254.0.1,进行地址转换");
|
||||
ip_NAT_packet.clear();
|
||||
ip_NAT_packet.position(0);
|
||||
|
||||
//更换ip包中目的地址为要转换的地址
|
||||
byte[] address_to_NAT_byte=new byte[4];
|
||||
int[] address_to_NAT_unsignedINT={192,168,3,2};
|
||||
int[] address_to_NAT_unsignedINT={192,168,3,12};
|
||||
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];
|
||||
}
|
||||
|
||||
//calculate the checksum of ip packet, replace the checksum
|
||||
short ip_checksum=computeChecksum(ipPackageData,ip_head_length,10);
|
||||
byte[] new_ip_checksum;
|
||||
new_ip_checksum=ByteHelper.uint16ToByteArray(Short.toUnsignedInt(ip_checksum));
|
||||
ipPackageData[10]=new_ip_checksum[0];
|
||||
ipPackageData[11]=new_ip_checksum[1];
|
||||
|
||||
//calculate the checksum of tcp,replace the checksum
|
||||
System.out.println("is tcp:"+Byte.toUnsignedInt(ipPackageData[9]));
|
||||
if(Byte.toUnsignedInt(ipPackageData[9])==6){
|
||||
byte[] temp_head_to_calculate_checksum;
|
||||
if((tcp_length+12)%2==0)
|
||||
temp_head_to_calculate_checksum=new byte[tcp_length+12];
|
||||
else
|
||||
temp_head_to_calculate_checksum=new byte[tcp_length+13];
|
||||
//构造tcp伪头部
|
||||
for(int i=0;i<8;i++)
|
||||
temp_head_to_calculate_checksum[i]=ipPackageData[i+12];
|
||||
temp_head_to_calculate_checksum[8]=ByteHelper.uint8ToByte(0);
|
||||
temp_head_to_calculate_checksum[9]=ipPackageData[9];
|
||||
temp_head_to_calculate_checksum[10]=ByteHelper.uint16ToByteArray(tcp_length)[0];
|
||||
temp_head_to_calculate_checksum[11]=ByteHelper.uint16ToByteArray(tcp_length)[1];
|
||||
for(int i=0;i<tcp_length;i++){
|
||||
temp_head_to_calculate_checksum[i+12]=ipPackageData[ip_head_length+i];
|
||||
}
|
||||
if((tcp_length+12)%2!=0)
|
||||
temp_head_to_calculate_checksum[tcp_length+12]=ByteHelper.uint8ToByte(0);
|
||||
|
||||
//printHexString("content of integrity tcp: ",temp_head_to_calculate_checksum);
|
||||
short tcp_checksum=computeChecksum(temp_head_to_calculate_checksum,tcp_length+12,28);
|
||||
//System.out.println("the checksum of tcp datagram is "+ Integer.toHexString(Short.toUnsignedInt(tcp_checksum)));
|
||||
byte[] new_tcp_checksum;
|
||||
new_tcp_checksum=ByteHelper.uint16ToByteArray(Short.toUnsignedInt(tcp_checksum));
|
||||
ipPackageData[ip_head_length+16]=new_tcp_checksum[0];
|
||||
ipPackageData[ip_head_length+17]=new_tcp_checksum[1];
|
||||
}
|
||||
|
||||
System.out.println("before changing, position is"+ip_NAT_packet.position());
|
||||
//搜一下怎么换ip地址,还要更换包里面其他的内容吗
|
||||
ip_NAT_packet.put(ipPackageData);
|
||||
|
||||
//从buffer中读取转换后的ip包
|
||||
|
||||
|
||||
|
||||
|
||||
// //从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
|
||||
// printHexString("the content of ip packet after changing is: ",ipdata_changing);
|
||||
// //读取源ip: [12]-[15] , 目的ip: [16]-[19],192.168.3.12
|
||||
// int[] ip_address_unsignedInt_changing=new int[8];
|
||||
// //将ip转化为unsigned int
|
||||
// for(int i=12;i<20;i++){
|
||||
@@ -238,13 +338,8 @@ public class MINVpnLBConnection implements MINVpnConnection {
|
||||
// System.out.print("."+ip_address_unsignedInt_changing[i]);
|
||||
// }
|
||||
// System.out.print("\n");
|
||||
// System.out.println("after changing, position is "+ip_NAT_packet.position());
|
||||
|
||||
try {
|
||||
outputStream.write(ip_NAT_packet.array(), 0, ip_NAT_packet.position());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
System.out.println("将抓转换后的地址写入tun网卡失败");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -254,9 +349,19 @@ public class MINVpnLBConnection implements MINVpnConnection {
|
||||
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("ip_NAT_packet position"+ip_NAT_packet.position());
|
||||
//
|
||||
// if()
|
||||
//
|
||||
//
|
||||
// ip_NAT_packet.position(0);
|
||||
// }
|
||||
// });
|
||||
// writeToTun.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());
|
||||
@@ -310,13 +415,56 @@ public class MINVpnLBConnection implements MINVpnConnection {
|
||||
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;
|
||||
/**
|
||||
* 将byte数组以16进制的形式输出
|
||||
*
|
||||
* @param b
|
||||
* byte[]
|
||||
* @return void
|
||||
*/
|
||||
public static void printHexString(String hint, byte[] b)
|
||||
{
|
||||
System.out.print(hint);
|
||||
for (int i = 0; i < b.length; i++)
|
||||
{
|
||||
String hex = Integer.toHexString(b[i] & 0xFF);
|
||||
if (hex.length() == 1)
|
||||
{
|
||||
hex = '0' + hex;
|
||||
}
|
||||
System.out.print(hex.toUpperCase() + " ");
|
||||
}
|
||||
System.out.println("");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Computes the IPv4 head checksum on the passed stream of bytes
|
||||
* representing the packet.
|
||||
*
|
||||
* @param data
|
||||
* The byte stream
|
||||
* @param length
|
||||
* The length of the IPv4 packet's head
|
||||
* @return The computed checksum
|
||||
*/
|
||||
short computeChecksum(byte[] data,int length,int checksumStart) {
|
||||
short checkSum;
|
||||
int sum = 0;
|
||||
int wordData;
|
||||
for (int i = 0; i <= length - 1; i = i + 2) {
|
||||
// Skip, if the current bytes are checkSum bytes
|
||||
if (i == checksumStart) {
|
||||
continue;
|
||||
}
|
||||
wordData = (data[i] << 8 & 0xFF00) + (data[i + 1] & 0xFF);
|
||||
sum = sum + wordData;
|
||||
}
|
||||
int carry = sum >> 16 & 0xFF;
|
||||
int finalSum = (sum & 0xFFFF) + carry;
|
||||
checkSum = (short) ~((short) finalSum & 0xFFFF);
|
||||
|
||||
return checkSum;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user