在沪务工的Polk、互拍👏👏👏
[技术]JAVA通过本地VPN-SOCKS代理请求外网
这个问题困扰几个礼拜的了,倒不是难而是根本没空查资料,也就大陆的用户使用VPN访问matters时会有此问题,记录一下。
现象是这样的: 1、我的mac可以正常通过程序访问matters(当然是开了vpn的) 2、我windows的http工具也是可以访问matters,比如postman,比如浏览器,比如idea自带的http工具(当然也是开了vpn的)
3、问题:唯独windows下通过程序无法访问matters,报下面的错误 org.apache.http.conn.ConnectTimeoutException: Connect to server.matters.news:443 [server.matters.news/103.39.76.66] failed: connect timed out 这导致我的mac已经开启好几周了,有点心疼。。。 其实问题都能猜到,肯定是程序没有走本地的vpn代理,即使设置了idea的代理也没效果,于是乎我只能搜索一个java访问本地socks代理的方法。
下面直接上代码了: import org.apache.http.HttpEntity; import org.apache.http.HttpHost; import org.apache.http.HttpResponse; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.DnsResolver; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.entity.StringEntity; 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.protocol.HttpContext; import org.apache.http.ssl.SSLContexts; import org.apache.http.util.EntityUtils; import javax.net.ssl.SSLContext; import java.io.IOException; import java.io.InputStream; import java.net.*; import java.util.Map; import java.util.Set; public class HttpProxyUtil { static 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 }) }; } } static class MyConnectionSocketFactory extends PlainConnectionSocketFactory { @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); } @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); } } static class MySSLConnectionSocketFactory extends SSLConnectionSocketFactory { public MySSLConnectionSocketFactory(final SSLContext sslContext) { // You may need this verifier if target site's certificate is not secure super(sslContext, ALLOW_ALL_HOSTNAME_VERIFIER); } @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); } @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); } } public static String getProxy(String url, Map<String,String> heads) { String result = null; Registry<ConnectionSocketFactory> reg = RegistryBuilder.<ConnectionSocketFactory> create() .register("http", new MyConnectionSocketFactory()) .register("https", new MySSLConnectionSocketFactory(SSLContexts.createSystemDefault())).build(); PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(reg, new FakeDnsResolver()); CloseableHttpClient httpclient = HttpClients.custom().setConnectionManager(cm).build(); HttpResponse httpResponse = null; InetSocketAddress socksaddr = new InetSocketAddress("127.0.0.1", 10808); HttpClientContext context = HttpClientContext.create(); context.setAttribute("socks.address", socksaddr); HttpGet request = new HttpGet(url); if(heads!=null){ Set<String> keySet=heads.keySet(); for(String s:keySet){ request.addHeader(s,heads.get(s)); } } System.out.println("Executing request " + request + " via SOCKS proxy " + socksaddr); try { httpResponse = httpclient.execute(request, context); HttpEntity httpEntity=httpResponse.getEntity(); if(httpEntity!=null){ result= EntityUtils.toString(httpEntity,"utf-8"); } } catch (IOException e) { e.printStackTrace(); } return result; } public static String postProxy(String url, Map<String,String> heads, String body) { String result = null; Registry<ConnectionSocketFactory> reg = RegistryBuilder.<ConnectionSocketFactory> create() .register("http", new MyConnectionSocketFactory()) .register("https", new MySSLConnectionSocketFactory(SSLContexts.createSystemDefault())).build(); PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(reg, new FakeDnsResolver()); CloseableHttpClient httpclient = HttpClients.custom().setConnectionManager(cm).build(); HttpResponse httpResponse = null; InetSocketAddress socksaddr = new InetSocketAddress("127.0.0.1", 10808); HttpClientContext context = HttpClientContext.create(); context.setAttribute("socks.address", socksaddr); HttpPost request = new HttpPost(url); if(heads!=null){ Set<String> keySet=heads.keySet(); for(String s:keySet){ request.addHeader(s,heads.get(s)); } } request.addHeader("Content-Type", "application/json;charset=utf-8"); //添加请求头 System.out.println("Executing request " + request + " via SOCKS proxy " + socksaddr); try { request.setEntity(new StringEntity(body,"utf-8")); httpResponse = httpclient.execute(request, context); HttpEntity httpEntity=httpResponse.getEntity(); if(httpEntity!=null){ result= EntityUtils.toString(httpEntity,"utf-8"); } } catch (IOException e) { e.printStackTrace(); } return result; } }
喜欢我的文章吗?
别忘了给点支持与赞赏,让我知道创作的路上有你陪伴。
发布评论…