Jetty HttpClient配置Socks4代理报错:SOCKS4隧道失败,错误码91
解决Jetty HttpClient使用SOCKS4代理报错code 91的问题
错误原因说明
SOCKS4协议中响应码91表示请求被拒绝,核心原因是SOCKS代理服务器无法连接到目标主机,常见场景包括:
- 目标主机网络不可达(防火墙拦截、目标服务下线)
- SOCKS4代理本身无权限访问目标主机(代理端白名单限制)
- 使用纯SOCKS4代理访问域名地址:SOCKS4不支持由代理解析域名,必须客户端提前解析为IP,否则代理无法识别目标地址
解决方案
1. 改用SOCKS4a代理(推荐)
SOCKS4a扩展了SOCKS4的功能,允许客户端直接发送域名,由代理服务器负责解析域名并连接目标主机。修改代码中代理实例的创建逻辑:
HttpClient httpClient = new HttpClient(); ProxyConfiguration proxyConfig = httpClient.getProxyConfiguration(); // 替换Socks4Proxy为Socks4aProxy Socks4aProxy proxy = new Socks4aProxy(socksHost, socksPort); proxyConfig.getProxies().add(proxy); httpClient.start(); String url = config.getProperty(stringUrl); Request request = httpClient.newRequest(url); request.method(HttpMethod.GET); request.onResponseContent(new BufferingResponseListener() { @Override public void onComplete(Result result) { String s = getContentAsString(); logger.debug("Received http response message: '{}', status: '{}'", s, result.getResponse().getReason()); } }); try { request.send(); } catch (Exception e) { throw new RuntimeException(e); }
2. 若坚持使用SOCKS4代理:手动解析域名并设置Host头
如果必须使用纯SOCKS4代理,需要先将目标URL的域名解析为IP,同时在请求中设置Host头,确保目标服务器能正确识别请求:
HttpClient httpClient = new HttpClient(); ProxyConfiguration proxyConfig = httpClient.getProxyConfiguration(); Socks4Proxy proxy = new Socks4Proxy(socksHost, socksPort); proxyConfig.getProxies().add(proxy); httpClient.start(); String url = config.getProperty(stringUrl); URI targetUri = new URI(url); // 解析域名到IP地址 InetAddress targetAddr = InetAddress.getByName(targetUri.getHost()); // 构造基于IP的请求URL String ipBasedUrl = String.format("%s://%s:%d%s", targetUri.getScheme(), targetAddr.getHostAddress(), targetUri.getPort() == -1 ? (targetUri.getScheme().equals("http") ? 80 : 443) : targetUri.getPort(), targetUri.getQuery() != null ? targetUri.getPath() + "?" + targetUri.getQuery() : targetUri.getPath() ); Request request = httpClient.newRequest(ipBasedUrl); request.method(HttpMethod.GET); // 设置Host头,匹配原域名 request.header(HttpHeader.HOST, targetUri.getHost()); request.onResponseContent(new BufferingResponseListener() { @Override public void onComplete(Result result) { String s = getContentAsString(); logger.debug("Received http response message: '{}', status: '{}'", s, result.getResponse().getReason()); } }); try { request.send(); } catch (Exception e) { throw new RuntimeException(e); }
3. 基础连通性排查
- 测试代理与目标主机的连通性:使用命令行工具验证,比如
curl -x socks4://{socksHost}:{socksPort} {targetUrl} - 检查SOCKS代理服务器的配置:确认代理是否允许访问目标主机的IP和端口,是否有IP白名单限制
- 核对代理地址、端口以及目标URL的正确性,避免拼写错误
内容的提问来源于stack exchange,提问作者Ihor Yutin
相关产品推荐
相关产品推荐

