mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-24 15:10:44 +01:00
route HttpClient over Socks5 proxy. requires apache http client. work in progress.
This commit is contained in:
parent
96f69ebfdf
commit
909bf4cab1
5 changed files with 189 additions and 2 deletions
|
@ -23,5 +23,12 @@
|
||||||
<artifactId>jtorproxy</artifactId>
|
<artifactId>jtorproxy</artifactId>
|
||||||
<version>${project.parent.version}</version>
|
<version>${project.parent.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
|
<artifactId>httpclient</artifactId>
|
||||||
|
<version>4.5</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
15
network/src/main/java/io/bitsquare/http/FakeDnsResolver.java
Normal file
15
network/src/main/java/io/bitsquare/http/FakeDnsResolver.java
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
package io.bitsquare.http;
|
||||||
|
|
||||||
|
import org.apache.http.conn.DnsResolver;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
|
// This class is adapted from
|
||||||
|
// http://stackoverflow.com/a/25203021/5616248
|
||||||
|
class FakeDnsResolver implements DnsResolver {
|
||||||
|
@Override
|
||||||
|
public InetAddress[] resolve(String host) throws UnknownHostException {
|
||||||
|
// Return some fake DNS record for every request, we won't be using it
|
||||||
|
return new InetAddress[] { InetAddress.getByAddress(new byte[] { 1, 1, 1, 1 }) };
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,24 +1,58 @@
|
||||||
package io.bitsquare.http;
|
package io.bitsquare.http;
|
||||||
|
|
||||||
|
import com.runjva.sourceforge.jsocks.protocol.Socks5Proxy;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.InputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.IOException;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
import org.apache.http.client.protocol.HttpClientContext;
|
||||||
|
import org.apache.http.config.Registry;
|
||||||
|
import org.apache.http.config.RegistryBuilder;
|
||||||
|
import org.apache.http.conn.socket.ConnectionSocketFactory;
|
||||||
|
import org.apache.http.conn.ssl.SSLContexts;
|
||||||
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import org.apache.http.impl.client.HttpClients;
|
||||||
|
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||||
|
import org.apache.http.util.EntityUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
|
||||||
// TODO route over tor
|
|
||||||
public class HttpClient {
|
public class HttpClient {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(HttpClient.class);
|
||||||
|
|
||||||
private final String baseUrl;
|
private final String baseUrl;
|
||||||
|
private final Socks5Proxy proxy;
|
||||||
|
|
||||||
public HttpClient(String baseUrl) {
|
public HttpClient(String baseUrl) {
|
||||||
this.baseUrl = baseUrl;
|
this.baseUrl = baseUrl;
|
||||||
|
this.proxy = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpClient(Socks5Proxy proxy, String baseUrl) {
|
||||||
|
this.baseUrl = baseUrl;
|
||||||
|
this.proxy = proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String requestWithGET(String param) throws IOException, HttpException {
|
public String requestWithGET(String param) throws IOException, HttpException {
|
||||||
|
return requestWithGETProxy(param);
|
||||||
|
// return proxy != null ? requestWithGETProxy(param) : requestWithGETNoProxy(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make an HTTP Get request directly (not routed over socks5 proxy).
|
||||||
|
*/
|
||||||
|
private String requestWithGETNoProxy(String param) throws IOException, HttpException {
|
||||||
HttpURLConnection connection = null;
|
HttpURLConnection connection = null;
|
||||||
try {
|
try {
|
||||||
|
log.info( "Executing HTTP request " + baseUrl + param + " proxy: none.");
|
||||||
URL url = new URL(baseUrl + param);
|
URL url = new URL(baseUrl + param);
|
||||||
connection = (HttpURLConnection) url.openConnection();
|
connection = (HttpURLConnection) url.openConnection();
|
||||||
connection.setRequestMethod("GET");
|
connection.setRequestMethod("GET");
|
||||||
|
@ -38,6 +72,51 @@ public class HttpClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make an HTTP Get request routed over socks5 proxy.
|
||||||
|
*/
|
||||||
|
private String requestWithGETProxy(String param) throws IOException, HttpException {
|
||||||
|
|
||||||
|
// This code is adapted from:
|
||||||
|
// http://stackoverflow.com/a/25203021/5616248
|
||||||
|
|
||||||
|
// Register our own SocketFactories to override createSocket() and connectSocket().
|
||||||
|
// connectSocket does NOT resolve hostname before passing it to proxy.
|
||||||
|
Registry<ConnectionSocketFactory> reg = RegistryBuilder.<ConnectionSocketFactory> create()
|
||||||
|
.register("http", new SocksConnectionSocketFactory())
|
||||||
|
.register("https", new SocksSSLConnectionSocketFactory(SSLContexts.createSystemDefault())).build();
|
||||||
|
|
||||||
|
// Use FakeDNSResolver if not resolving DNS locally.
|
||||||
|
// This prevents a local DNS lookup (which would be ignored anyway)
|
||||||
|
PoolingHttpClientConnectionManager cm = proxy.resolveAddrLocally() ?
|
||||||
|
new PoolingHttpClientConnectionManager(reg) :
|
||||||
|
new PoolingHttpClientConnectionManager(reg, new FakeDnsResolver());
|
||||||
|
CloseableHttpClient httpclient = HttpClients.custom().setConnectionManager(cm).build();
|
||||||
|
try {
|
||||||
|
// InetSocketAddress socksaddr = new InetSocketAddress(proxy.getInetAddress(), proxy.getPort());
|
||||||
|
|
||||||
|
// remove me: Use this to test with system-wide Tor proxy.
|
||||||
|
InetSocketAddress socksaddr = new InetSocketAddress("127.0.0.1", 9050);
|
||||||
|
|
||||||
|
HttpClientContext context = HttpClientContext.create();
|
||||||
|
context.setAttribute("socks.address", socksaddr);
|
||||||
|
|
||||||
|
HttpGet request = new HttpGet(baseUrl + param);
|
||||||
|
|
||||||
|
log.error( "Executing request " + request + " proxy: " + socksaddr);
|
||||||
|
CloseableHttpResponse response = httpclient.execute(request, context);
|
||||||
|
try {
|
||||||
|
InputStream stream = response.getEntity().getContent();
|
||||||
|
String buf = convertInputStreamToString(stream);
|
||||||
|
return buf;
|
||||||
|
} finally {
|
||||||
|
response.close();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
httpclient.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private String convertInputStreamToString(InputStream inputStream) throws IOException {
|
private String convertInputStreamToString(InputStream inputStream) throws IOException {
|
||||||
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
|
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
package io.bitsquare.http;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.Proxy;
|
||||||
|
import java.net.Socket;
|
||||||
|
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
|
||||||
|
import org.apache.http.HttpHost;
|
||||||
|
import org.apache.http.protocol.HttpContext;
|
||||||
|
|
||||||
|
// This class is adapted from
|
||||||
|
// http://stackoverflow.com/a/25203021/5616248
|
||||||
|
//
|
||||||
|
// This class routes connections over Socks, and avoids resolving hostnames locally.
|
||||||
|
class SocksConnectionSocketFactory extends PlainConnectionSocketFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* creates an unconnected Socks Proxy socket
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Socket createSocket(final HttpContext context) throws IOException {
|
||||||
|
InetSocketAddress socksaddr = (InetSocketAddress) context.getAttribute("socks.address");
|
||||||
|
Proxy proxy = new Proxy(Proxy.Type.SOCKS, socksaddr);
|
||||||
|
return new Socket(proxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* connects a Socks Proxy socket and passes hostname to proxy without resolving it locally.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Socket connectSocket(int connectTimeout, Socket socket, HttpHost host, InetSocketAddress remoteAddress,
|
||||||
|
InetSocketAddress localAddress, HttpContext context) throws IOException {
|
||||||
|
// Convert address to unresolved
|
||||||
|
InetSocketAddress unresolvedRemote = InetSocketAddress
|
||||||
|
.createUnresolved(host.getHostName(), remoteAddress.getPort());
|
||||||
|
return super.connectSocket(connectTimeout, socket, host, unresolvedRemote, localAddress, context);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package io.bitsquare.http;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.Proxy;
|
||||||
|
import java.net.Socket;
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||||
|
import org.apache.http.HttpHost;
|
||||||
|
import org.apache.http.protocol.HttpContext;
|
||||||
|
|
||||||
|
// This class is adapted from
|
||||||
|
// http://stackoverflow.com/a/25203021/5616248
|
||||||
|
//
|
||||||
|
// This class routes connections over Socks, and avoids resolving hostnames locally.
|
||||||
|
class SocksSSLConnectionSocketFactory extends SSLConnectionSocketFactory {
|
||||||
|
|
||||||
|
public SocksSSLConnectionSocketFactory(final SSLContext sslContext) {
|
||||||
|
|
||||||
|
// Only allow connection's to site's with valid certs.
|
||||||
|
super(sslContext, STRICT_HOSTNAME_VERIFIER);
|
||||||
|
|
||||||
|
// Or to allow insecure (eg self-signed certs)
|
||||||
|
// super(sslContext, ALLOW_ALL_HOSTNAME_VERIFIER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* creates an unconnected Socks Proxy socket
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Socket createSocket(final HttpContext context) throws IOException {
|
||||||
|
InetSocketAddress socksaddr = (InetSocketAddress) context.getAttribute("socks.address");
|
||||||
|
Proxy proxy = new Proxy(Proxy.Type.SOCKS, socksaddr);
|
||||||
|
return new Socket(proxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* connects a Socks Proxy socket and passes hostname to proxy without resolving it locally.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Socket connectSocket(int connectTimeout, Socket socket, HttpHost host, InetSocketAddress remoteAddress,
|
||||||
|
InetSocketAddress localAddress, HttpContext context) throws IOException {
|
||||||
|
// Convert address to unresolved
|
||||||
|
InetSocketAddress unresolvedRemote = InetSocketAddress
|
||||||
|
.createUnresolved(host.getHostName(), remoteAddress.getPort());
|
||||||
|
return super.connectSocket(connectTimeout, socket, host, unresolvedRemote, localAddress, context);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue