複数の IP アドレスをホストするサーバーが多数あります。追加のものは、いわゆる仮想 IP (「VIP」) です。
Java アプリが、ホスト IP アドレスではなく指定された仮想 IP を送信元アドレスとしてリストする発信接続を作成できるようにしたいと考えています。
これが私たちが試したことです。にリストされている IP アドレスInetAddress#getByAddress
は、仮想 IP アドレスです。プロパティurl
は、接続先のユーザー指定のターゲット URL です。
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();
}
}
上記のコードは、この回答をモデルにしています
これを Python の でテストしておりSimpleHTTPServer
、単純に実行python -m SimpleHTTPServer
して接続を試みています。
Java コードでプロキシを使用しない場合、接続は正しく機能します。
ただし、VIP プロキシが定義されるとすぐに、接続が拒否されます。
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.<init>(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)
理由はありますか?
アップデート
ソケットのローカル アドレスを直接指定すると、プロセスは正常に機能します。
上記で使用したのと同じように、ポート 8000 でリッスンする Python シンプル ソケット サーバーをセットアップしますSimpleHTTPServer
。目的のローカル アドレスを持つソケットを使用して Java からこれに接続すると、期待どおりに機能しました。Python サーバーは、着信接続ソース アドレスをユーザーが定義したものとして認識しました。
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();
作成されたすべてのソケットをSocket#setSocketImplFactory
カスタマイズすることで問題を解決できるかどうかを調べます。
問題は、 と の両方Socket#setSocketImplFactory
でURL.setURLStreamHandlerFactory
デフォルトの実装をオーバーライドできるが、デフォルトの実装にアクセスできないことです。上にロジックを追加したいだけの場合、これは非常に面倒です。