当前位置:   article > 正文

【网络排障/自签证书踩坑】curl: (35) OpenssL SSL connect: Connection reset by peer in connection to_curl35 connect reset by peer

curl35 connect reset by peer

前言

最近在对接业务的时候,需要请求云上厂家的接口。

首先说明一点,云是属于内网环境的,且调用是HTTPS协议的,所以厂家使用到了自签证书。而自签证书在对于不处于同一内部网络的机器,在进行HTTPS请求的时候,就会遇到SSL验证无法通过的问题,如以下。

curl: (35) OpenssL SSL connect: Connection reset by peer in connection to ip:port
  • 1

第一步

你要确定的是,你的请求只是因为绕不过去SSL验证。如果你中间还套了一层网闸,或者其他网络转发的话,那么即时你使用下方的解决思路,也是错误的。因为很有可能你的本机地址映射出去的IP并不是你用 ip addr命令输出的地址,这点你要确定好。

第二步

非常重要的事,使用telnet ip port,测试网络连接情况,如果能够正常建立起连接,那么说明你的请求是可以出去你所处的云网络的。

第三步

简单测试,使用curl命令进行排障,先把接口使用postman等工具编辑好后生成curl语句,并且在生成的语句内添加上 -k 或者 --insecure,如果能正常返回业务结果,那么就可以开始尝试写绕过SSL验证的代码了。

具体代码下方已经给出。

工具类:

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class SslUtils {
	private static void trustAllHttpsCertificates() throws Exception {
		TrustManager[] trustAllCerts = new TrustManager[1];
		TrustManager tm = new miTM();
		trustAllCerts[0] = tm;
		SSLContext sc = SSLContext.getInstance("SSL");
		sc.init(null, trustAllCerts, null);
		HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
	}
	static class miTM implements TrustManager,X509TrustManager {
		public X509Certificate[] getAcceptedIssuers() {
			return null;
		}
		public boolean isServerTrusted(X509Certificate[] certs) {
			return true;
		}
		public boolean isClientTrusted(X509Certificate[] certs) {
			return true;
		}
		public void checkServerTrusted(X509Certificate[] certs, String authType)
				throws CertificateException {
			return;
		}
		public void checkClientTrusted(X509Certificate[] certs, String authType)
				throws CertificateException {
			return;
		}
	}
	/**
	 * 忽略HTTPS请求的SSL证书
	 */
	public static void ignoreSsl() throws Exception{
		HostnameVerifier hv = new HostnameVerifier() {
			public boolean verify(String urlHostName, SSLSession session) {
				log.debug("Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost());
				return true;
			}
		};
		trustAllHttpsCertificates();
		HttpsURLConnection.setDefaultHostnameVerifier(hv);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

POST请求方法:

import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;

public class SolutionServiceImpl {
    //post 请求,自动绕开SSL验证
    public String postRequest(String urlAddress,String args,int timeOut) throws Exception{
        URL url = new URL(urlAddress);
        if("https".equalsIgnoreCase(url.getProtocol())){
            SslUtils.ignoreSsl();//忽略掉SSL异常
        }
        URLConnection u = url.openConnection();
        u.setRequestProperty("Content-Type", "application/json");
        u.setRequestProperty("Authorization", "Bearer *****");
        //设置请求头
        u.setDoInput(true);
        u.setDoOutput(true);
        u.setConnectTimeout(timeOut);
        u.setReadTimeout(timeOut);
        OutputStreamWriter osw = new OutputStreamWriter(u.getOutputStream(), "UTF-8");
        osw.write(args);
        osw.flush();
        osw.close();
        u.getOutputStream();
        return IOUtils.toString(u.getInputStream());
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

写一个Api结果构造类:

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class ApiResultVO<T> {
	private String code;
	private String msg;
	private List<T> data;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

使用方法:

import cn.hutool.core.lang.TypeReference;

private static final String baseUrl = "https://ip:port/api";

//接口偏移
private static final String requestUrl = "/requestData";

private static Integer timeout = 10000;

public class SolutionServiceImpl {

    public Map<String,Object>  getAlarmJqListByTime(RequestForm form) throws Exception {
        String apiresult =  postRequest(baseUrl+requestUrl, parseJSON(form), timeout);
        ApiResultVO<APIVO> resList =  JSONUtil.toBean(apiresult,new TypeReference<ApiResultVO<APIVO>>(){},false);//ApiResultVO使用的是泛型,APIVO就是你的实体类了

        ///
        ///
    }

    private String parseJSON(RequestForm form) {
        JSONObject param = new JSONObject();
        param.put("param",form.getParam());
        return param.toString();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

总结:

有一种情况,是某个机构已经把你的云主机IP映射到接口厂家的同一片网络上,但这并不代表你就能直接HTTPS请求对方的接口,这一点是需要注意的。当然这中间怎么做的网络映射,笔者也没有完全了解,可能观点是片面的,欢迎指点。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Li_阴宅/article/detail/794964
推荐阅读
相关标签
  

闽ICP备14008679号