Wednesday, December 17, 2008

SSH Tips-and-Tricks

I have some ssh tips that I'm using time to time to connect to the university servers. This is cool because I can use the software from the university labs while being at home. So I don't need to drive 20 km both ways just for a single experiment.

X11 forwarding

You can encrypt X sessions over SSH. Not only is the traffic encrypted, but the DISPLAY environment variable on the remote system is set properly. So, if you are running X on your local computer, your remote X applications magically appear on your local screen.

You can enable X11 forwarding with ssh -X host.

Compressing data

SSH can use gzip compression on any connection. The default compression level is equivalent to approximately 4x compression for text. Compression is a great idea if you are forwarding X sessions on a dial-up or slow network. Turn on compression with ssh -C.

Roaming behind the firewall.

Suppose you have to connect to machines, that are located in some remote place behind a firewall. The gateway "G" is a remote server that has the authority to connect to those machines.

What we would like to do is to use any kind of X11 UI on workstation A, for instance. We need two ssh tunnels to connect to the workstations. With the first tunnel we will remap the local port using -L option. The general syntax will be:

ssh -L{local_port}:{workstation}:{remote_port} {user}@{hostname}

After this the gateway will become transparent for us. The second tunnel created for localhost will actually go forward to the gateway and connect to {workstation}.

ssh -X -o "HostKeyAlias {workstation}" {user}@localhost

Given the example above, let's try to connect user "ant" to the workstation "corona" via "aragorn" gateway. Note that we want to use X11 forwarding to be able to work with graphical environment. There are several ways to do this. I'll describe two possible solutions here (assuming that you have M$ Windows running on your PC).


With Cygwin environment one may get the connection to the workstation using following steps.

  1. Start cygwing environment

  2. Start X11 environment, type strartx

  3. Ensure you have at least two xterm windows. Type xterm & to start another xterm

  4. Create first SSH tunnel: ssh -L2222:corona:22 ant@aragorn

  5. In another xterm window create the second SSH tunnel: ssh -X -C -o "HostKeyAlias corona" -p 2222 ant@localhost

To verify is the X forwarding works fine, just type any app. name to the remote xterm, like xclock - and the xclock application should open on your machine while actually running on the remote host.

WinAxe + Putty

If you don't have cygwin environment installed and you're unwilling to install it, then we have another solution here. WinAxe and putty can be used to create the same SSH tunnels as with cygwin. Follow the steps:

  1. Install WinAxe, and run XSession

  2. Start putty, specify the connection parameters and create a tunnel as shown on the pictures below.

  3. Start another putty window and create new tunnel against localhost with X-forwarding enabled.

After putty sessions are started you can do the same trick again as with cygwin, start a remote application so that it looks like running on your machine.

Tuesday, December 2, 2008

Oracle 10g JDBC driver and BigDecimal.toString()

I would like to share an issue with you regarding Oracle 10g JDBC driver and migration to Java 5.

Recently we encountered a production bug where a client got some extra money on his/her account. The bug appeared with Oracle JDBC driver (ojdbc14.jar) version once we migrated the application to Java 5 from Java 1.4.

In order to safe the precision in Java it is the common practice to use BigDecimals. Oracle driver, while binding the objects to SQL types, is calling BigDecimal.toString() method. In Java 5, the method was altered in order to support JSR-13:Decimal Arithmetic Enhancement standard. This issue exists in Sun bug database

Here's a piece of code to reproduce this problem:
-- table for the test
create table test_table ( value number )

// java code to reproduce the behaviour
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class HelloFromOracle {
public static void main(String[] args) throws Exception {
Connection connection = DriverManager.getConnection("jdbc:oracle:thin:user/passwd@DB:1521:SID");
String query = "insert into test_table values (?)";
PreparedStatement stmt = connection.prepareStatement(query);
BigDecimal bd = new BigDecimal("0.000000000000001");
stmt.setBigDecimal(1, bd);

Now, with Oracle driver v the value in database will be:
> select * from test_table

... And with Oracle driver v
> select * from test_table

So my message is to replace the Oracle driver to, especially with migration to Java 5 from Java 1.4. What is interesting is that oracle driver doesn't suffer from this problem.

Disqus for Code Impossible