mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-24 07:07:43 +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>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>4.5</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</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;
|
||||
|
||||
import com.runjva.sourceforge.jsocks.protocol.Socks5Proxy;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.InetSocketAddress;
|
||||
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 {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(HttpClient.class);
|
||||
|
||||
private final String baseUrl;
|
||||
private final Socks5Proxy proxy;
|
||||
|
||||
public HttpClient(String 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 {
|
||||
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;
|
||||
try {
|
||||
log.info( "Executing HTTP request " + baseUrl + param + " proxy: none.");
|
||||
URL url = new URL(baseUrl + param);
|
||||
connection = (HttpURLConnection) url.openConnection();
|
||||
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 {
|
||||
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
|
||||
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