Apache Emulation Part 2

In this blog we will be continuing with the theme of replacing Apache for the purposes of simplifying the post-install Jaxer environment. So we have Apache which accepts http request, and we have mod-jaxer which processes the requests received from Apache. So we need to figure out how these two processes interact with each other.

const fs = require('fs');
const APACHE_PORT = 4330;
const JAXER_PORT = 4327;


const server = net.createServer(function(socket) {

        let count = 0;
        const client = new net.Socket();

        client.connect(JAXER_PORT, '127.0.0.1', function() {
                console.log('Connected (this should only happen once!)');
        });

        client.on('data', function(data) {
                console.log("Got data from Jaxer!");
                console.log(data);
                console.log(data.toString('ascii'));
                console.log("-------- End --------");
                writeFile("jaxer", data);
                socket.write(data);
        });

        client.on('close', function() {
                console.log('Client Connection closed');
        });

        socket.on('data', function(data) {
                console.log("Got Data from Apache!");
                console.log(data);
                console.log(data.toString('ascii'));
                console.log("-------- End ---------");
                writeFile("apache", data);
                client.write(data);
        });

        socket.on('close', function() {
                console.log("Connection from %s closed", socket.remoteAddress + ':' + socket.remotePort);
        });

        function writeFile(from, data) {

                let num = count.toString(16);
                count++;
                while(num.length < 3) {
                        num = "0" + num;
                }

                let filename = "packets/" + num + "_" + from + ".bin";
                fs.writeFile(filename, data, function(err) {
                        if(err) {
                                throw err;
                        }
                });
        }

});

server.listen(APACHE_PORT, '127.0.0.1');
console.log("Proxy server listening on port %s", APACHE_PORT);

In order to figure out how these two processes interact with each other, we can use a somewhat crude man-in-the-middle approach. Normally Apache and Mod-Jaxer communicate over the tcp port 4237. Right now as far as I can tell the port seems to be hard coded into Jaxer, which means the easiest option seems to be to redirect Apache to use a different port, 4330 in this case, and then we can set up a simple echo server that will take packets from Apache and send them to mod-Jaxer, and likewise return packets from mod-jaxer to Apache.

Effectively what we’ve done is create our own simple tcpdump that we can use to start analyzing and replicating the packets sent from Apache to mod-jaxer in order to start emulating Apache’s functionality with a different http server.

So to start off with, we’re going to start as simple as possible and start working our way up. So for the client we’ll be using curl to reduce the number of header, and we’ll be using a few very simple, very short html files to start working on the basic interaction. And luckily what we find is that for at least the basic interactions functions the fundamentals seem to be pretty simple.

So start off with Apache will send a handshake to mod-jaxer with the bytes 000003000402 and mod-jaxer will reply with 000003000401. From there Apache will send another tcp request with http headers received from the client in mixed case, headers appended on the server with upper case, followed by the content of the file to mod-jaxer, and then mod-jaxer will return the content body of the response.

So in the next blog we will cover the structure of the packet or data that Apache send to mod-jaxer that includes the client and server headers, as it looks like if we are able to replicate that request, we can at least start implementing some basic functionality as far as replacing the http server.