views:

467

answers:

2

I need to create a program that receives HTTP request and forwards those requests to the web servers.

Diagram

I have successfully made this using only Java Sockets but the client needed the program to be implemented in Jpcap. I'd like to know if this is possible and what literature I should be reading for this project.

This is what I have now by stitching together pieces from the Jpcap tutorial:

import java.net.InetAddress;
import java.io.*;
import jpcap.*;
import jpcap.packet.*;


public class Router {
    public static void main(String args[]) {
        //Obtain the list of network interfaces
        NetworkInterface[] devices = JpcapCaptor.getDeviceList();

        //for each network interface
        for (int i = 0; i < devices.length; i++) {
            //print out its name and description
            System.out.println(i+": "+devices[i].name + "(" + devices[i].description+")");

            //print out its datalink name and description
            System.out.println(" datalink: "+devices[i].datalink_name + "(" + devices[i].datalink_description+")");

            //print out its MAC address
            System.out.print(" MAC address:");
            for (byte b : devices[i].mac_address)
                System.out.print(Integer.toHexString(b&0xff) + ":");
            System.out.println();

            //print out its IP address, subnet mask and broadcast address
            for (NetworkInterfaceAddress a : devices[i].addresses)
                System.out.println(" address:"+a.address + " " + a.subnet + " "+ a.broadcast);
        }

        int index = 1;  // set index of the interface that you want to open.

        //Open an interface with openDevice(NetworkInterface intrface, int snaplen, boolean promics, int to_ms)
        JpcapCaptor captor = null;
        try {
            captor = JpcapCaptor.openDevice(devices[index], 65535, false, 20);
            captor.setFilter("port 80 and host 192.168.56.1", true);
        } catch(java.io.IOException e) {
            System.err.println(e);
        }

        //call processPacket() to let Jpcap call PacketPrinter.receivePacket() for every packet capture.
        captor.loopPacket(-1,new PacketPrinter());

        captor.close();
    }
}

class PacketPrinter implements PacketReceiver {
    //this method is called every time Jpcap captures a packet
    public void receivePacket(Packet p) {
        JpcapSender sender = null;
        try {
            NetworkInterface[] devices = JpcapCaptor.getDeviceList();
            sender = JpcapSender.openDevice(devices[1]);
        } catch(IOException e) {
            System.err.println(e);
        }


        IPPacket packet = (IPPacket)p;

        try {
            // IP Address of machine sending HTTP requests (the client)
            // It's still on the same LAN as the servers for testing purposes.
            packet.dst_ip = InetAddress.getByName("192.168.56.2");
        } catch(java.net.UnknownHostException e) {
            System.err.println(e);
        }

        //create an Ethernet packet (frame)
        EthernetPacket ether=new EthernetPacket();
        //set frame type as IP
        ether.frametype=EthernetPacket.ETHERTYPE_IP;
        //set source and destination MAC addresses

        // MAC Address of machine running reverse proxy server
        ether.src_mac = new MacAddress("08:00:27:00:9C:80").getAddress();
        // MAC Address of machine running web server
        ether.dst_mac = new MacAddress("08:00:27:C7:D2:4C").getAddress();

        //set the datalink frame of the packet as ether
        packet.datalink=ether;

        //send the packet
        sender.sendPacket(packet);

        sender.close();

        //just print out a captured packet
        System.out.println(packet);
    }
}

Any help would be greatly appreciated. Thank you.

A: 

Why? What are his reasons? Does he really want to pay ten times the cost for the same thing you've already done?

You don't need Jpcap to implement HTTP proxies. It can be done entirely within java.net or java.nio.

EJP
Because they wrote on their thesis that they'll use Jpcap. :))
Ramon Marco Navarro
@EJB. Agree and wonder what the benefit of writing such a thing would be given all the open source stuff out there. Is this perhaps a homework assignment? Is the "client" some student who doesn't want to do his own project?
ShabbyDoo
I'm sorry. I forgot to check this answer. I'm finished with this project and just used socket programming. Way easier and I don't see the benefit of doing it "raw" in this case.
Ramon Marco Navarro
A: 

I don't think you can make this happen, at least on a Windows box. Jpcap is just a wrapper for Winpcap, and this underlying mechanism can not drop observed packets:

http://www.mirrorservice.org/sites/ftp.wiretapped.net/pub/security/packet-capture/winpcap/misc/faq.htm#Q-17

So, I don't see how you can build a reverse proxy "on the wire." Wouldn't you have to do the following:

  1. Observe an incoming HTTP request by piecing together packets in real-time AND dropping them from being received by the intended host.

  2. Make the alternate HTTP request based on whatever proxy rules you are implementing.

  3. Grab the response from your request and push out packets on the wire which fake a response from the original host?

Since you can't drop the inbound packets, won't the intended host attempt to handle the request and throw packets of its own onto the wire in response? There's probably even more that I don't know about as I'm no networking expert. This question just made me curious about what would be possible using such a "shim".

ShabbyDoo
Before I went the socket programming route, I really did try implementing this using JPCap. What I did was: I sniffed the exchange of nginx on reverse proxy mode with a client computer and another computer running webserver. Using the data from the "experiment", I tried to do it using JPCap instead of nginx, but got stuck on how the client computer automatically selects an available port from where the other computer could connect. I'm sure that's not just the problem that I would encounter if I did continue going the JPCap route.
Ramon Marco Navarro
Also, IIRC, nginx didn't drop any packets coming from the client computer. I might be wrong though.
Ramon Marco Navarro