// Copyright (c) 2015 D1SM.net package net.fs.cap; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.Inet4Address; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Random; import java.util.concurrent.LinkedBlockingQueue; import net.fs.rudp.Route; import net.fs.utils.ByteShortConvert; import net.fs.utils.MLog; import org.pcap4j.core.NotOpenException; import org.pcap4j.core.PacketListener; import org.pcap4j.core.PcapHandle; import org.pcap4j.core.PcapNativeException; import org.pcap4j.core.PcapNetworkInterface; import org.pcap4j.core.PcapNetworkInterface.PromiscuousMode; import org.pcap4j.core.PcapStat; import org.pcap4j.core.Pcaps; import org.pcap4j.packet.EthernetPacket; import org.pcap4j.packet.EthernetPacket.EthernetHeader; import org.pcap4j.packet.IllegalPacket; import org.pcap4j.packet.IllegalRawDataException; import org.pcap4j.packet.IpV4Packet; import org.pcap4j.packet.IpV4Packet.IpV4Header; import org.pcap4j.packet.Packet; import org.pcap4j.packet.TcpPacket; import org.pcap4j.packet.TcpPacket.TcpHeader; import org.pcap4j.util.MacAddress; public class CapEnv { public MacAddress gateway_mac; public MacAddress local_mac; Inet4Address local_ipv4; public PcapHandle sendHandle; VDatagramSocket vDatagramSocket; String testIp_tcp=""; String testIp_udp="5.5.5.5"; String selectedInterfaceName=null; String selectedInterfaceDes=""; PcapNetworkInterface nif; private final int COUNT=-1; private final int READ_TIMEOUT=1; private final int SNAPLEN= 10*1024; HashMap<Integer, TCPTun> tunTable=new HashMap<Integer, TCPTun>(); LinkedBlockingQueue<Packet> packetList=new LinkedBlockingQueue<Packet>(); Random random=new Random(); boolean client=false; short listenPort; TunManager tcpManager=null; CapEnv capEnv; Thread versinMonThread; boolean detect_by_tcp=true; public boolean tcpEnable=false; public boolean fwSuccess=true; boolean ppp=false; { capEnv=this; } public CapEnv(boolean isClient,boolean fwSuccess){ this.client=isClient; this.fwSuccess=fwSuccess; tcpManager=new TunManager(this); } public void init() throws Exception{ initInterface(); Thread thread_process=new Thread(){ public void run(){ while(true){ try { Packet packet=packetList.take(); EthernetPacket packet_eth=(EthernetPacket) packet; EthernetHeader head_eth=packet_eth.getHeader(); IpV4Packet ipV4Packet=null; if(ppp){ ipV4Packet=getIpV4Packet_pppoe(packet_eth); }else { if(packet_eth.getPayload() instanceof IpV4Packet){ ipV4Packet=(IpV4Packet) packet_eth.getPayload(); } } if(ipV4Packet!=null){ IpV4Header ipV4Header=ipV4Packet.getHeader(); if(ipV4Packet.getPayload() instanceof TcpPacket){ TcpPacket tcpPacket=(TcpPacket) ipV4Packet.getPayload(); TcpHeader tcpHeader=tcpPacket.getHeader(); if(client){ TCPTun conn=tcpManager.getTcpConnection_Client(ipV4Header.getSrcAddr().getHostAddress(),tcpHeader.getSrcPort().value(), tcpHeader.getDstPort().value()); if(conn!=null){ conn.process_client(capEnv,packet,head_eth,ipV4Header,tcpPacket,false); } }else { TCPTun conn=null;conn = tcpManager.getTcpConnection_Server(ipV4Header.getSrcAddr().getHostAddress(),tcpHeader.getSrcPort().value()); if( tcpHeader.getDstPort().value()==listenPort){ if(tcpHeader.getSyn()&&!tcpHeader.getAck()&&conn==null){ conn=new TCPTun(capEnv,ipV4Header.getSrcAddr(),tcpHeader.getSrcPort().value()); tcpManager.addConnection_Server(conn); } conn = tcpManager.getTcpConnection_Server(ipV4Header.getSrcAddr().getHostAddress(),tcpHeader.getSrcPort().value()); if(conn!=null){ conn.process_server(packet,head_eth,ipV4Header,tcpPacket,true); } } } }else if(packet_eth.getPayload() instanceof IllegalPacket){ MLog.println("IllegalPacket!!!"); } } } catch (InterruptedException e) { e.printStackTrace(); } catch (IllegalRawDataException e) { e.printStackTrace(); } } } }; thread_process.start(); Thread systemSleepScanThread=new Thread(){ public void run(){ long t=System.currentTimeMillis(); while(true){ if(System.currentTimeMillis()-t>5*1000){ for(int i=0;i<10;i++){ MLog.info("休眠恢复... "+(i+1)); try { boolean success=initInterface(); if(success){ MLog.info("休眠恢复成功 "+(i+1)); break; } } catch (Exception e1) { e1.printStackTrace(); } try { Thread.sleep(5*1000); } catch (InterruptedException e) { e.printStackTrace(); } } } t=System.currentTimeMillis(); try { Thread.sleep(1*1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }; systemSleepScanThread.start(); } PromiscuousMode getMode(PcapNetworkInterface pi){ PromiscuousMode mode=null; String string=(pi.getDescription()+":"+pi.getName()).toLowerCase(); if(string.contains("wireless")){ mode=PromiscuousMode.NONPROMISCUOUS; }else { mode=PromiscuousMode.PROMISCUOUS; } return mode; } boolean initInterface() throws Exception{ boolean success=false; detectInterface(); List<PcapNetworkInterface> allDevs = Pcaps.findAllDevs(); MLog.println("Network Interface List: "); for(PcapNetworkInterface pi:allDevs){ String desString=""; if(pi.getDescription()!=null){ desString=pi.getDescription(); } MLog.info(" "+desString+" "+pi.getName()); if(pi.getName().equals(selectedInterfaceName) &&desString.equals(selectedInterfaceDes)){ nif=pi; //break; } } if(nif!=null){ String desString=""; if(nif.getDescription()!=null){ desString=nif.getDescription(); } success=true; MLog.info("Selected Network Interface:\n"+" "+desString+" "+nif.getName()); if(fwSuccess){ tcpEnable=true; } }else { tcpEnable=false; MLog.info("Select Network Interface failed,can't use TCP protocal!\n"); } if(tcpEnable){ sendHandle = nif.openLive(SNAPLEN,getMode(nif), READ_TIMEOUT); final PcapHandle handle= nif.openLive(SNAPLEN, getMode(nif), READ_TIMEOUT); final PacketListener listener= new PacketListener() { @Override public void gotPacket(Packet packet) { try { if(packet instanceof EthernetPacket){ packetList.add(packet); } } catch (Exception e) { e.printStackTrace(); } } }; Thread thread=new Thread(){ public void run(){ try { handle.loop(COUNT, listener); PcapStat ps = handle.getStats(); handle.close(); } catch (Exception e) { e.printStackTrace(); } } }; thread.start(); } if(!client){ MLog.info("FinalSpeed server start success."); } return success; } void detectInterface() { List<PcapNetworkInterface> allDevs = null; HashMap<PcapNetworkInterface, PcapHandle> handleTable=new HashMap<PcapNetworkInterface, PcapHandle>(); try { allDevs = Pcaps.findAllDevs(); } catch (PcapNativeException e1) { e1.printStackTrace(); return; } for(final PcapNetworkInterface pi:allDevs){ try { final PcapHandle handle = pi.openLive(SNAPLEN, getMode(pi), READ_TIMEOUT); handleTable.put(pi, handle); final PacketListener listener= new PacketListener() { @Override public void gotPacket(Packet packet) { try { if(packet instanceof EthernetPacket){ EthernetPacket packet_eth=(EthernetPacket) packet; EthernetHeader head_eth=packet_eth.getHeader(); if(head_eth.getType().value()==0xffff8864){ ppp=true; PacketUtils.ppp=ppp; } IpV4Packet ipV4Packet=null; IpV4Header ipV4Header=null; if(ppp){ ipV4Packet=getIpV4Packet_pppoe(packet_eth); }else { if(packet_eth.getPayload() instanceof IpV4Packet){ ipV4Packet=(IpV4Packet) packet_eth.getPayload(); } } if(ipV4Packet!=null){ ipV4Header=ipV4Packet.getHeader(); if(ipV4Header.getSrcAddr().getHostAddress().equals(testIp_tcp)){ local_mac=head_eth.getDstAddr(); gateway_mac=head_eth.getSrcAddr(); local_ipv4=ipV4Header.getDstAddr(); selectedInterfaceName=pi.getName(); if(pi.getDescription()!=null){ selectedInterfaceDes=pi.getDescription(); } //MLog.println("local_mac_tcp1 "+gateway_mac+" gateway_mac "+gateway_mac+" local_ipv4 "+local_ipv4); } if(ipV4Header.getDstAddr().getHostAddress().equals(testIp_tcp)){ local_mac=head_eth.getSrcAddr(); gateway_mac=head_eth.getDstAddr(); local_ipv4=ipV4Header.getSrcAddr(); selectedInterfaceName=pi.getName(); if(pi.getDescription()!=null){ selectedInterfaceDes=pi.getDescription(); } //MLog.println("local_mac_tcp2 local_mac "+local_mac+" gateway_mac "+gateway_mac+" local_ipv4 "+local_ipv4); } //udp if(ipV4Header.getDstAddr().getHostAddress().equals(testIp_udp)){ local_mac=head_eth.getSrcAddr(); gateway_mac=head_eth.getDstAddr(); local_ipv4=ipV4Header.getSrcAddr(); selectedInterfaceName=pi.getName(); if(pi.getDescription()!=null){ selectedInterfaceDes=pi.getDescription(); } //MLog.println("local_mac_udp "+gateway_mac+" gateway_mac"+gateway_mac+" local_ipv4 "+local_ipv4); } } } } catch (Exception e) { e.printStackTrace(); } } }; Thread thread=new Thread(){ public void run(){ try { handle.loop(COUNT, listener); PcapStat ps = handle.getStats(); handle.close(); } catch (Exception e) { //e.printStackTrace(); } } }; thread.start(); } catch (PcapNativeException e1) { } } //detectMac_udp(); try { detectMac_tcp(); } catch (UnknownHostException e) { e.printStackTrace(); } Iterator<PcapNetworkInterface> it=handleTable.keySet().iterator(); while(it.hasNext()){ PcapNetworkInterface pi=it.next(); PcapHandle handle=handleTable.get(pi); try { handle.breakLoop(); } catch (NotOpenException e) { e.printStackTrace(); } //handle.close();//linux下会阻塞 } } IpV4Packet getIpV4Packet_pppoe(EthernetPacket packet_eth) throws IllegalRawDataException{ IpV4Packet ipV4Packet=null; byte[] pppData=packet_eth.getPayload().getRawData(); if(pppData.length>8&&pppData[8]==0x45){ byte[] b2=new byte[2]; System.arraycopy(pppData, 4, b2, 0, 2); short len=(short) ByteShortConvert.toShort(b2, 0); int ipLength=toUnsigned(len)-2; byte[] ipData=new byte[ipLength]; //设置ppp参数 PacketUtils.pppHead_static[2]=pppData[2]; PacketUtils.pppHead_static[3]=pppData[3]; if(ipLength==(pppData.length-8)){ System.arraycopy(pppData, 8, ipData, 0, ipLength); ipV4Packet=IpV4Packet.newPacket(ipData, 0, ipData.length); }else { MLog.println("长度不符!"); } } return ipV4Packet; } public static String printHexString(byte[] b) { StringBuffer sb=new StringBuffer(); for (int i = 0; i < b.length; i++) { String hex = Integer.toHexString(b[i] & 0xFF); hex= hex.replaceAll(":", " "); if (hex.length() == 1) { hex = '0' + hex; } sb.append(hex + " "); } return sb.toString(); } public void createTcpTun_Client(String dstAddress,short dstPort) throws Exception{ Inet4Address serverAddress=(Inet4Address) Inet4Address.getByName(dstAddress); TCPTun conn=new TCPTun(this,serverAddress,dstPort,local_mac,gateway_mac); tcpManager.addConnection_Client(conn); boolean success=false; for(int i=0;i<6;i++){ try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } if(conn.preDataReady){ success=true; break; } } if(success){ tcpManager.setDefaultTcpTun(conn); }else { tcpManager.removeTun(conn); tcpManager.setDefaultTcpTun(null); throw new Exception("创建隧道失败!"); } } private void detectMac_tcp() throws UnknownHostException{ InetAddress address=InetAddress.getByName("www.bing.com"); final int por=80; testIp_tcp=address.getHostAddress(); for(int i=0;i<5;i++){ try { Route.es.execute(new Runnable() { @Override public void run() { try { Socket socket=new Socket(testIp_tcp,por); socket.close(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }); Thread.sleep(500); if(local_mac!=null){ break; } } catch (Exception e) { e.printStackTrace(); try { Thread.sleep(1); } catch (InterruptedException e1) { e1.printStackTrace(); } } } } private void detectMac_udp(){ for(int i=0;i<10;i++){ try { DatagramSocket ds=new DatagramSocket(); DatagramPacket dp=new DatagramPacket(new byte[1000], 1000); dp.setAddress(InetAddress.getByName(testIp_udp)); dp.setPort(5555); ds.send(dp); ds.close(); Thread.sleep(500); if(local_mac!=null){ break; } } catch (Exception e) { e.printStackTrace(); try { Thread.sleep(1); } catch (InterruptedException e1) { e1.printStackTrace(); } } } } public short getListenPort() { return listenPort; } public void setListenPort(short listenPort) { this.listenPort = listenPort; if(!client){ MLog.info("Listen tcp port: "+toUnsigned(listenPort)); } } public static int toUnsigned(short s) { return s & 0x0FFFF; } }