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

前言

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

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

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

第一步

你要确定的是,你的请求只是因为绕不过去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);
	}
}

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());
    }
}

写一个Api结果构造类:

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class ApiResultVO<T> {
	private String code;
	private String msg;
	private List<T> data;
}

使用方法:

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();
    }
}

总结:

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值