更换目的地址、tcp端口,计算ip包、tcp报文字段中的校验和,并写回tun网卡中。下一步研究tun网卡的流量流向,以及如何、从何读出地址修改后的ip包。

This commit is contained in:
liubohahaha committed 2021-08-30 22:27:08 +08:00
1 parent 9368d21267
commit de51fdec72
1 file changed
+172 -24
@@ -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;
}
}