Simple Proxy Server in Java

In this post, I am going to show how a simple Proxy server can be designed in Java which will provide the core functionalities of a proxy. From Wikipedia, “a proxy server is a server (a computer system or an application program) that acts as an intermediary for requests from clients seeking resources from other servers.“The proxy server generally has some resources, or has access to some resources and when it receives request from a client, it access the appropriate resource and sends back the response.

So it serves two purposes, giving access to a resource which the client do not have access and it hides the real client who needs the resource. The second part is used for the anonymous browsing in Internet using anonymous proxy servers. Although this may not be as “anonymous” as it sounds because the proxy server which you connect to can maintain logs about the clients who are connecting to the server, and also the bigger risk being the data theft. Since the “anonymous” proxy server has access to all the request you send, there is risk of that data being exposed unless there is some kind of encryption in place between the client and the proxy server.

If you are in a network, and the machine which you are using don’t have access to Internet but another machine in the same subnet has access to Internet, then you can run this proxy application in the machine which has Internet access and in your local machine, you can configure your web browser to use the IP and Port number of the machine where the proxy is running in the LAN/Network settings. Once done, you should be able to access the Internet. This is one of the practical use for proxy servers.

The proxy server which we will be designing will be a simple HTTP proxy which gets web requests based on HTTP protocol and sends back response in the same protocol. We will start by declaring some constants.

int proxyServerPortNumber = 7879;
int webServerPortNumber = 80;
String webServerIpAddress = "192.168.1.1";
final int PROXY_SERVER_TIME_OUT = 5000;
final int SOCKET_TIME_OUT = 2000;

proxyServerPortNumber defines the port where the proxy server will be listening. You can use any port number which is not used by other process / standard port.

webServerIpAddress and webServerPortNumber defines the IP/port where the server can access the resources. Since we are designing this to access websites over http, the port is defined as 80 and the IP should be a machine which has Internet access (can be localhost too)

PROXY_SERVER_TIME_OUT and SOCKET_TIME_OUT are standard parameters defined for Server and network socket timeout. You can adjust this based on your needs.

Now we need to start the Java class to bind to the port number defined and to run in a infinite loop or as a daemon thread, so that it keeps on listening for requests. In this example, we will be using the infinite loop.

try {
    serverSocket = new ServerSocket(proxyServerPortNumber);
} catch(Exception exc) {
        System.exit(0);
}

Now the process will be listening in the port 7879 for requests from clients. Now, let’s open an infinte loop and make a connection to the resource, in our case the web server.

socketProxy = new Socket(InetAddress.getByName(webServerIpAddress),webServerPortNumber);
socketProxy.setSoTimeout(PROXY_SERVER_TIME_OUT);
socket = serverSocket.accept();
socket.setSoTimeout(SOCKET_TIME_OUT);
inputStream = socket.getInputStream();

The request from the client will be received by Input Stream, so once we are connected, we will be sending this Input Stream which is nothing but a normal HTTP REQ object to the server which has the resource or as in our case the machine connected to Internet. The server will respond with the response which will be a HTTP RES over the Java Output Stream. We will be forwarding this output stream to the client which will be rendered in the application which the client requested in. That is if the request was sent through command line, the entire HTML will be printed, if its a browser the page will be rendered.

try {
    while( (intCounter = in.read()) != -1) {
        if(intCounter == -1) break;
        if(!bREQ)
            bREQ = true;
        pOutputStream.write(intCounter);
        if(byteCheckFl > 0) {
            break;
        }
        if(intCounter == 13 && intPrevCounter == 10)
            byteCheckFl++;
        intPrevCounter = intCounter;
    }
} catch(Exception e) {
    if(!bREQ) {
        continue;
    }
}

pOutputStream.flush();
pIutputStream = socketProxy.getInputStream();
outputStream = socket.getOutputStream();
try {
    while( (intCounter = pIutputStream.read()) != -1) {
        outputStream.write(intCounter);
    }
} catch(Exception e) {
}
outputStream.flush();

Make sure to close all the opened sockets and connections once the response is sent. Since this whole code is running in an infinite loop, the server will keep on waiting for the requests and sending the responses back. This is a crude implementation of the concept and there is room for a lot more improvements (like supporting SSL), but this should serve as a foundation to make the proxy a robust one.

We can easily make this Java class as a Win32 service, so that it will always run in background and starts along with the OS. That will need some work with JNI. I will explain that in a later post.

Recover Database Passwords from Weblogic Server

In this post, I am going to explain how to Decrypt or recover the passwords which are encrypted (or hashed) in Weblogic 8.1 especially the database passwords. If you ever forgot the database password which is already configured with Weblogic or the password for the user which is used to start Weblogic, this will be handy. The hashed passwords can be normally found in config.xml and boot.properties inside the application domain. The database passwords will be in config.xml under the JDBC configuration and will look something like below.

$ PasswordEncrypted="{3DES}bDcllidskanDsaIsnaiG=="

To recover the passwords, we need some prerequisites which are listed below.

  1. weblogic.jar & jsafeFIPS.jar from the Weblogic server. (You can find this under WL_HOME/server/lib directory)
  2. SerializedSystemIni.dat from the application domain (You can find this under the application domain root)
  3. The encrypted password from config.xml / boot.properties including {3DES}

SerializedSystemIni.dat has the key to recover the passwords so this is absolutely essential and it should be from the same server since the key depends on the machine. If you are not able to find this file, then probably the server administrator hasn’t given read access to this file to all the users. For Production systems that should be a practice, only the id which will be starting the weblogic server should have read permissions to the SerializedSystemIni.dat file. If not, this will be a security risk, its like leaving the key for your Home on the street. Coming back to the subject, if you got the file then you are all set for the next step.

Assuming you have all the files needed, let’s proceed to the next step. You can copy all the prerequisite files to your workstation or if needed you can run the utility from the server too. As long as the machines have JDK installed it should be fine.

To recover the passwords we will be using a utility from Apache Geronimo 2.0.1 API - Weblogic81Utils.java. Although this file is a part of a package, this can be run as a standalone class with little modification. All you need to do is to remove the package reference and add a main() method to the class. The code for main() method is below.

public static void main(String args[]) {
    try{
        String beaDir = "$Server/lib or the Directory which has the requried JAR files$";
        String appDir = "$App Domain or the Directory which has SerializedSystemIni.dat$";
        String hashedPassword = "{3DES}Vdsds76nGsfdsfKJbg54ss==";
        Weblogic81Utils weblogic81Utils = new Weblogic81Utils(beaDir, appDir);
        String plainTextPassword = weblogic81Utils.decryptString(hashedPassword);
        String configXML = weblogic81Utils.getConfigXML();
        Properties bootProperties = (Properties) weblogic81Utils.getBootProperties();
        System.out.println("-----------------------------------------------------");
        System.out.println("hashedPassword" + " == " + plainTextPassword);
        System.out.println("boot.properties" + " <username> "
            + bootProperties.getProperty("username"));
        System.out.println("boot.properties" + " <password> "
            + bootProperties.getProperty("password"));
        System.out.println("-----------------------------------------------------");
    } catch (Exception e) {
        throw (RuntimeException)new IllegalArgumentException("Unable to initialize"
            + "encryption routines from provided arguments").initCause(e);
    }
}

beaDir - If you are running this on the server, it will be the $WL_HOME/server/lib directory. If you are running elsewhere it will be the path which has weblogic.jar and jsafeFIPS.jar.

appDir - If you are running this on the server, it will be your application domain directory. If you are running elsewhere, it will be the path which contains SerializedSystemIni.dat, config.xml and boot.properties.

hashedPassword – In this example, I am not reading config.xml directly instead I give the encrypted password as a input. So this will be the encrypted database password from your config.xml.

Save the class file and we are all set to run the program. Make sure you removed the package reference since we are running this as a standalone program. No other change is required. Compile the class and run the class. I tested this using JDK 1.6, but any JDK higher than 1.4 should work.

Sample output is given below.

This was tested with Weblogic Server 8.1 and JDK 1.6.