拦截和修改特定数据包(IPv4 / TCP)

时间:2016-11-21 20:32:06

标签: java tcp packets

我正在尝试拦截数据包并能够阻止它们进入/传出特定域

为了做到这一点,我使我的(java)程序将域添加到hosts文件,重定向到我自己的公共ipv4地址(这无关紧要,它不能是真正的IP,我必须能够拦截它,重定向到我自己的IP,确保世界上没有其他人收到它)。其次,我让程序监听该信号并将其重新发送到真实服务器的不同源端口。 (已经处理了校验和更改)现在计划是接收响应并执行完全相同的操作,但现在通过编辑源ip(在本例中为我自己的公共IP)和目标端口

这应该创建一个程序,我在连接之间是一种中间人

但它没有按预期工作,当我得到服务器的响应(标志SYN / ACK)时,它会自动从我随机选择的端口发回一个RST标志(IPv4 / TCP),这是不一样的作为真实客户端的端口

我不知道是否有更好的方法可以做到这一点(可能有)以及如何防止我遇到的问题,我无法在互联网上找到类似的东西。任何形式的帮助/提示都将不胜感激

请记住,我现在正在使用jnetpscape,继续我正在做的事情会很高兴

编辑(代码):

这是“HConnection”课程(没有完全展示但是所有重要的事情):

public class HConnection    {

private volatile int state = -1;           // current state of the program
private volatile boolean HostFileEdited = false;
private volatile String domain = null;
private volatile boolean waitingConnection = false;

private volatile String ipOfDomain = null; // string of the server adress
private volatile byte[] ipofdomb;         //4 bytes of the server adress

private volatile String myIpAdr = null;   //my IP adress
private volatile byte[] myIpb;            //my public IP in 4 bytes

private volatile byte[] port = null;      //port of proxy
private volatile byte[] falseport = null; //port of client


private volatile ServerSocket server;

public HConnection()    {
    try {
        server = new ServerSocket(0);
        byte[] tempPortb = ByteBuffer.allocate(4).putInt(server.getLocalPort()).array();
        System.out.println(server.getLocalPort());
        port = new byte[]{tempPortb[2], tempPortb[3]};
        (new Thread() {
              public void run() {
                    try {
                        server.accept();
                    } catch (IOException e) {
                        System.out.println(e.getMessage());
                    }
              }
        }).start();
        state = 0;


    } catch (UnknownHostException e) {System.out.println("fail");} catch (IOException e) {System.out.println("fail");}
}


public String getPublicIP ()    {
    try{

        myIpAdr =  new BufferedReader(new InputStreamReader(new URL("http://checkip.amazonaws.com/").openStream())).readLine();
        System.out.println(myIpAdr);
        InetAddress ip = InetAddress.getByName(myIpAdr);
        myIpb = ip.getAddress();
        return myIpAdr;
    }
    catch (Exception e){}
    return null;
}

public void setUrl(String domain)   {
    this.domain = domain;
}

public int getState()   {
    return state;
}

public void prepare()   {
    try{
        URL urlofsite = new URL("https://"+domain);
        InetAddress address = InetAddress.getByName(urlofsite.getHost());
        ipOfDomain = address.getHostAddress();
        System.out.println(ipOfDomain);
        ipofdomb = address.getAddress();

        addToHostsFile(getPublicIP() + "\t" + domain);

        state = 1;
    }
    catch(Exception e){}
}

public void abort() {

    removeFromHostsFile(domain);
    HostFileEdited = false;

    state = -1;

    try {
        server.close();
    } catch (IOException e) {   }

    waitingConnection = false;
}

public void awaitConnection()   {
    if (state == 1) {
        waitingConnection = true;

        System.out.println("stap1");

        StringBuilder errbuf = new StringBuilder();     // For any error msgs  
        int snaplen = 64 * 1024;           // Capture all packets, no truncation  
        int flags = Pcap.MODE_PROMISCUOUS; // capture all packets  
        int timeout = 0;           // 10 seconds in millis  
        Pcap pcap = Pcap.openLive("wlp4s0", snaplen, flags, timeout, errbuf);  
        if (pcap == null) {  
              System.err.printf("Error while opening device for capture: "  
                    + errbuf.toString());  
              return;  
        }

        PcapHeader hdr = new PcapHeader(JMemory.POINTER);  
        JBuffer buf = new JBuffer(JMemory.POINTER);
        int id = JRegistry.mapDLTToId(pcap.datalink());  

        while (HostFileEdited && waitingConnection && state == 1 && pcap.nextEx(hdr, buf) == Pcap.NEXT_EX_OK)   {

                PcapPacket packet = new PcapPacket(hdr, buf);  

                try {
                    packet.scan(id);
                    TcpPacket pkt = new TcpPacket(packet);
                    if (pkt.isTcp())    {
                        if (pkt.destinationIPequals(myIpAdr) && pkt.getDestinationPort() == 443 && (falseport == null || Arrays.equals(pkt.getSourcePortb(), falseport)))   {
                            if (falseport == null)  {
                                falseport = pkt.getSourcePortb();
                            }

                            pkt.changeDestinationIP(ipofdomb);
                            pkt.changeSourcePort(port);
                            pkt.iPchecksumFix();
                            pkt.tcPchecksumFix();
                            ByteBuffer b = ByteBuffer.wrap(pkt.getPacketInBytes());

                            System.out.println("10");
                            System.out.println("OUT"+ (pcap.sendPacket(b)));

                        }
                        else if (pkt.sourceIPequals(ipOfDomain) && pkt.getSourcePort() == 443 && falseport != null && Arrays.equals(pkt.getDestinationPortb(),port) )   {

                            pkt.changeSourceIP(myIpb);
                            pkt.changeDestinationPort(falseport);
                            pkt.iPchecksumFix();
                            pkt.tcPchecksumFix();
                            ByteBuffer b = ByteBuffer.wrap(pkt.getPacketInBytes());

                            System.out.println("IN"+ pcap.sendPacket(b));
                        }

                    }

                }
                catch (Exception e) {}

        }
        System.out.println("stap2");
        if (state == 1 && waitingConnection == true)    state = 2;
        waitingConnection = false;
    }

}
}

“awaitConnection()”方法目前正在发生大多数事情。但这只是我的计划的开始

从主类(SWT Designer)调用HConnection:

private Button btnNewButton_1;
private HConnection connectie;

private void btnConnect_clicked(SelectionEvent e) throws InterruptedException {

    if (btnNewButton_1.getText().equals("Connect")) {
        String Url = combo.getText();
        connectie = new HConnection();
        connectie.setUrl(Url);
        connectie.prepare();

        lblNewLabel_2.setText("Waiting -> client");

        new Thread(new Runnable() {
              public void run() {
                    connectie.awaitConnection();

                    Display.getDefault().asyncExec(new Runnable() {
                        public void run() {
                            if (connectie.getState() == 2)  {
                                lblNewLabel_2.setText("Replacing URL");
                            }
                            else    {
                                lblNewLabel_2.setText("Failed");
                                connectie.abort();
                                btnNewButton_1.setText("Connect");
                            }
                        }
                    });
                    if (connectie.getState() == 2)  {
                        // go on with the rest of the program


                    }
              }
        }).start();

        btnNewButton_1.setText("Abort");
    }
    else if(btnNewButton_1.getText().equals("Abort"))   {
        connectie.abort();

        lblNewLabel_2.setText("Aborted");
        btnNewButton_1.setText("Connect");
    }



}

1 个答案:

答案 0 :(得分:0)

以下代码接受连接,但不保留对生成的Socket实例的引用。此Socket符合垃圾回收条件,当发生这种情况时,它会自动关闭。然后,向该套接字发送数据的客户端将收到RST。

public void run() {
  try {
    server.accept();
  } catch (IOException e) {
    System.out.println(e.getMessage());
  }
}