title: Java: Specifying the local address for an outgoing connection
body: <p>We've many servers which host multiple IP addresses. The additional ones are so-called Virtual IPs (&quot;VIPs&quot;).</p>
  <p>We'd like to enable a Java app to make an outgoing connection which lists as source address a designated Virtual IP rather than the host ip address.</p>
  <p>Here's what we've tried. The ip address listed in <code>InetAddress#getByAddress</code> is the virtual ip address. The property <code>url</code> is a user-specified target url to  connect to.</p>
  <pre><code>public void attemptConnection() {
    try {
      Proxy proxy = new Proxy(Proxy.Type.HTTP,
          new InetSocketAddress(InetAddress.getByAddress(new byte[]{(byte)10,(byte)252,(byte)47,(byte)33}), 0));
      final URL _url = new URL(url);
      final URLConnection conn = _url.openConnection(proxy);
      BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
      String inputLine;
      while ((inputLine = in.readLine()) != null) {
        System.out.println(inputLine);
        in.close();
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  </code></pre>
  <p>The code above was modelled on <a href="https://stackoverflow.com/questions/91678/how-can-i-specify-the-local-address-on-a-java-net-urlconnection">this answer</a></p>
  <p>We're testing this with Python's <code>SimpleHTTPServer</code>, simply running <code>python -m SimpleHTTPServer</code> then trying to connect.</p>
  <p>If we use no proxy in our Java code then the connection works correctly.</p>
  <p>However, as soon as the VIP proxy is defined we get connection refused:</p>
  <pre><code>java.net.ConnectException: Connection refused
          at java.net.PlainSocketImpl.socketConnect(Native Method)
          at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:327)
          at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:193)
          at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:180)
          at java.net.Socket.connect(Socket.java:546)
          at java.net.Socket.connect(Socket.java:495)
          at sun.net.NetworkClient.doConnect(NetworkClient.java:178)
          at sun.net.www.http.HttpClient.openServer(HttpClient.java:409)
          at sun.net.www.http.HttpClient$2.run(HttpClient.java:457)
          at java.security.AccessController.doPrivileged(Native Method)
          at sun.net.www.http.HttpClient.privilegedOpenServer(HttpClient.java:454)
          at sun.net.www.http.HttpClient.openServer(HttpClient.java:521)
          at sun.net.www.http.HttpClient.&lt;init&gt;(HttpClient.java:240)
          at sun.net.www.http.HttpClient.New(HttpClient.java:321)
          at sun.net.www.http.HttpClient.New(HttpClient.java:338)
          at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:935)
          at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:914)
          at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:801)
          at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1139)
          at com.ocado.dsi.ConnectToUrl.attemptConnection(ConnectToUrl.java:38)
          at com.ocado.dsi.ConnectToUrl.run(ConnectToUrl.java:56)
          at com.ocado.dsi.ConnectToUrl.main(ConnectToUrl.java:64)
  </code></pre>
  <p>Any ideas why?</p>
  <h2>Update</h2>
  <p>When specifying the local address on a socket directly the process works fine.</p>
  <p>I setup a Python simple socket server listening on port 8000 just as the <code>SimpleHTTPServer</code> used above does. Connecting to this from Java using a socket with the desired local address worked as expected: the python server recognised the incoming connection source address as that defined by the user.</p>
  <pre><code>Socket s = new Socket(InetAddress.getByAddress(new byte[]{(byte)10,(byte)252,(byte)47,(byte)33}), 8000, InetAddress.getByAddress(new byte[]{(byte)10,(byte)97,(byte)5,(byte)147}), 0);
  s.close();
  </code></pre>
  <p>I'm going to dig into <code>Socket#setSocketImplFactory</code> to see whether the problem can be resolved by customising every created socket.</p>
  <p>The problem is that both <code>Socket#setSocketImplFactory</code> and <code>URL.setURLStreamHandlerFactory</code> enable you to override the default implementation but do not give you access to the default implementation, so they seem to be very much all-or-nothing overrides. This is very annoying when you only wish tor add logic on top.</p>