diff --git a/app/src/main/java/com/pkusz/min_vpn_client/services/minsocks/MINVpnLBConnection.java b/app/src/main/java/com/pkusz/min_vpn_client/services/minsocks/MINVpnLBConnection.java index 561ea50..12d9fb3 100644 --- a/app/src/main/java/com/pkusz/min_vpn_client/services/minsocks/MINVpnLBConnection.java +++ b/app/src/main/java/com/pkusz/min_vpn_client/services/minsocks/MINVpnLBConnection.java @@ -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 { +// 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; } - }