首页 > 编程问答 >如何在 java 或 python 中使用 HTTP(S) 解决无法解析的主机名或无法识别的名称错误?

如何在 java 或 python 中使用 HTTP(S) 解决无法解析的主机名或无法识别的名称错误?

时间:2024-08-04 15:00:17浏览次数:15  
标签:python java ssl https python-requests

我尝试以编程方式访问网站的信息,但在 Java 和 Python 上都无法解析主机名。如果我指定 IP 地址,则会将错误更改为 TLSV1_UNRECOGNIZED_NAME。不过,这个网站无需任何额外的工作就可以通过任何浏览器解决。

我在这里浏览了很多潜在的解决方案,但对于 Python,它说这个问题应该在 2.7 或 2.8 中得到解决,但我正在使用3.10 仍然出现该错误。在 Java 中,它声称这是一个已知错误,但提供的解决方案(例如通过编译选项删除 SNI 标头,或将空主机名数组传递给 HTTPSURLConnection 以取消 SNI 标头的创建)并不能解决该问题。我还尝试按照此处答案的建议将用户代理设置为 Mozilla,但这也没有改变任何内容。

我确信该网站有些不寻常,但它不是我拥有的,所以我无法检查太多有关其配置的信息。

具体来说,我想查看的网站是:

URL -> https://epic7db.com/heroes
IP -> 157.230.84.20
DNS Lookup -> https://www.nslookup.io/domains/epic7db.com/webservers/

在本地使用 nslookup 时,我返回:

nslookup epic7db.com
Server:  UnKnown
Address:  10.0.0.1

Non-authoritative answer:
Name:    epic7db.com
Address:  157.230.84.20

任何帮助将不胜感激,因为我本质上是在扔东西墙看看此时粘着什么。

编辑:添加代码示例 Python:

import requests

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.76 Safari/537.36'} # This is chrome, you can set whatever browser you like
url = 'https://epic7db.com'
a = requests.get(url,headers)
print(a.content)

Kotlin 使用 Java 的 HttpsUrlConnection:

import http.SSLSocketFactoryWrapper
import java.net.URL
import javax.net.ssl.*


fun main() {

    HttpsURLConnection.setDefaultHostnameVerifier { hostName, session -> true }
    val url = URL("https://epic7db.com")
    val sslParameters = SSLParameters()
    val sniHostNames: MutableList<SNIHostName> = ArrayList<SNIHostName>(1)
//    sniHostNames.add(SNIHostName(url.getHost()))
    sslParameters.setServerNames(sniHostNames as List<SNIServerName>?)
    val wrappedSSLSocketFactory: SSLSocketFactory =
        SSLSocketFactoryWrapper(SSLContext.getDefault().socketFactory, sslParameters)
    HttpsURLConnection.setDefaultSSLSocketFactory(wrappedSSLSocketFactory)

    val conn = url.openConnection() as HttpsURLConnection
    conn.hostnameVerifier = HostnameVerifier { s: String?, sslSession: SSLSession? -> true }
    println(String(conn.inputStream.readAllBytes()))
}

Kotlin/Java 中建议的帮助器类:

package http;

import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

public class SSLSocketFactoryWrapper extends SSLSocketFactory {

    private final SSLSocketFactory wrappedFactory;
    private final SSLParameters sslParameters;

    public SSLSocketFactoryWrapper(SSLSocketFactory factory, SSLParameters sslParameters) {
        this.wrappedFactory = factory;
        this.sslParameters = sslParameters;
    }

    @Override
    public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
        SSLSocket socket = (SSLSocket) wrappedFactory.createSocket(host, port);
        setParameters(socket);
        return socket;
    }

    @Override
    public Socket createSocket(String host, int port, InetAddress localHost, int localPort)
            throws IOException, UnknownHostException {
        SSLSocket socket = (SSLSocket) wrappedFactory.createSocket(host, port, localHost, localPort);
        setParameters(socket);
        return socket;
    }


    @Override
    public Socket createSocket(InetAddress host, int port) throws IOException {
        SSLSocket socket = (SSLSocket) wrappedFactory.createSocket(host, port);
        setParameters(socket);
        return socket;
    }

    @Override
    public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
        SSLSocket socket = (SSLSocket) wrappedFactory.createSocket(address, port, localAddress, localPort);
        setParameters(socket);
        return socket;

    }

    @Override
    public Socket createSocket() throws IOException {
        SSLSocket socket = (SSLSocket) wrappedFactory.createSocket();
        setParameters(socket);
        return socket;
    }

    @Override
    public String[] getDefaultCipherSuites() {
        return wrappedFactory.getDefaultCipherSuites();
    }

    @Override
    public String[] getSupportedCipherSuites() {
        return wrappedFactory.getSupportedCipherSuites();
    }

    @Override
    public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
        SSLSocket socket = (SSLSocket) wrappedFactory.createSocket(s, host, port, autoClose);
        setParameters(socket);
        return socket;
    }

    private void setParameters(SSLSocket socket) {
        socket.setSSLParameters(sslParameters);
    }

}

你遇到的问题与网站的服务器配置有关,特别是与它如何处理服务器名称指示 (SNI) 相关。下面我会解释一下原因和可能的解决方案:

问题根源:

服务器名称指示 (SNI) 是 TLS 扩展,它允许客户端在 TLS 握手的早期阶段指定他们想要连接的主机名。这对于在单个 IP 地址上托管多个基于 HTTPS 的网站的服务器至关重要。

你遇到的网站似乎在 SNI 配置方面有问题。它可能使用不支持 SNI 的旧版 TLS 库或配置错误。这意味着:

  1. 当你的浏览器发送 SNI 信息时,服务器无法正确理解它。 然而,由于浏览器会回退到非 SNI 行为,它仍然能够建立连接(这可能使用默认证书或 IP 地址关联的第一个证书)。

  2. 当你的 Python 和 Java 代码尝试连接时,它们正确发送 SNI 信息。 但是,由于服务器配置错误,连接失败,并出现 "无法解析主机名" 或 "TLSV1_UNRECOGNIZED_NAME" 错误。

可能的解决方案:

  1. 禁用 SNI(不推荐):

    • 不推荐这样做,因为它不安全,并且可能会导致其他问题。
    • 禁用 SNI 意味着你的客户端将在不指定主机名的情况下建立 TLS 连接。这可能会导致服务器返回错误的证书,从而导致连接错误或安全漏洞。
  2. 使用支持 SNI 回退的 HTTP 库:

    • 一些 HTTP 库(尤其是较旧的库)可能无法正确处理 SNI 回退。考虑使用更新的库,这些库明确支持 SNI 回退。
    • 对于 Python, requests 库应该可以正常处理 SNI 回退。 确保你使用的是最新版本。
    • 对于 Java,请考虑使用更新的 HTTP 客户端库,例如 Apache HttpClient 或 OkHttp。 这些库通常具有更好的 SNI 支持。
  3. 联系网站所有者:

    • 最好的解决方案是联系网站所有者,并告知他们这个问题。他们可以调查并修复其服务器配置以正确支持 SNI。

代码改进建议:

尽管代码本身并不是问题的根源,但你可以进行一些改进:

Python:

import requests

headers = {'User-Agent': 'Mozilla/5.0'} 
# 无需指定完整的用户代理字符串,除非特定网站需要它
url = 'https://epic7db.com'

try:
  response = requests.get(url, headers=headers)
  response.raise_for_status()  # 检查 HTTP 错误
  print(response.content)
except requests.exceptions.RequestException as e:
  print(f"请求出错: {e}")

Kotlin:

import java.net.URL
import java.net.UnknownHostException
import javax.net.ssl.HttpsURLConnection
import javax.net.ssl.SSLContext

fun main() {
    val urlString = "https://epic7db.com"

    try {
        val url = URL(urlString)
        val connection = url.openConnection() as HttpsURLConnection

        // 设置更宽松的 HostnameVerifier (仅用于测试!)
        connection.hostnameVerifier = { _, _ -> true } 

        println(connection.inputStream.bufferedReader().use { it.readText() })

    } catch (e: UnknownHostException) {
        println("无法解析主机名: ${e.message}")
    } catch (e: Exception) {
        println("请求出错: ${e.message}")
    }
}

总结:

你遇到的问题很可能是由于网站服务器的 SNI 配置错误造成的。虽然禁用 SNI 或使用支持 SNI 回退的 HTTP 库可以作为临时解决方法,但联系网站所有者并要求他们修复服务器配置才是最佳的长期解决方案。

标签:python,java,ssl,https,python-requests
From: 78830224

相关文章

  • Java对象流
    对象流对象输入流java.io.ObjectInputStream使用对象流可以进行对象反序列化构造器ObjectInputStream(InputStreamin)将当前创建的对象输入流链接在指定的输入流上方法ObjectreadObject()进行对象反序列化并返回。该方法会从当前对象输入流链接的流中读取若干......
  • Python 请求 POST 请求与 websockets 库一起使用时挂起
    我使用Python中的requests库发送POST请求,同时维护与websockets库的WebSocket连接:importasyncioimportrequestsimportwebsocketsasyncdefwebsocket_handler(uri):asyncwithwebsockets.connect(uri)aswebsocket:whileTrue:me......
  • 在Python中,list1[::] = list2的空间复杂度是多少?
    此代码首先迭代列表nums,更新整数0、1、2(也分别称为红色、白色和蓝色)的计数。nums保证只有整数0、1和/或2。找到计数后,代码使用[::],这是一种就地修改列表的技巧,以排序numsdefsortColors(self,nums:List[int])->None:re......
  • JavaScript Proxy() 构造函数、Proxy对象
    Proxy()构造函数Proxy()构造函数用于创建Proxy对象。语法newProxy(target,handler)可以使用Proxy()构造函数来创建一个新的Proxy对象。构造函数接收两个必须的参数:target是要创建的对象,即要使用Proxy包装的目标对象(可以是任何类型的对象,包括原生数组,函数......
  • Java - 异常与File
    异常灵魂四问:如果try中没有遇到问题,怎么执行?try全部执行,catch不执行如果try中可能会遇到多个问题,怎么执行?写多个catch与之对应,父类异常需要写在下面如果try中遇到的问题没有被捕获,怎么执行?异常会默认交给虚拟机处理,try...catch白写如果try中遇到了问题,那......
  • [附开题]flask框架高校资产管理系统d8y3s(源码+论文+python)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着高等教育事业的快速发展,高校资产规模日益庞大,种类繁多,管理难度显著增加。传统的资产管理方式往往依赖于手工记录和纸质档案,不仅效率低......
  • [附开题]flask框架贺州图特产管理系统uuy79(源码+论文+python)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景贺州,这座历史悠久、文化底蕴深厚的城市,以其丰富的自然资源和独特的地理位置孕育了众多令人瞩目的特产。然而,在信息化快速发展的今天,贺州特......
  • [附开题]flask框架红枫超市会员管理系统ew5iq(源码+论文+python)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着零售行业的快速发展与消费者需求的日益多样化,超市作为人们日常生活中不可或缺的一部分,其管理效率和服务质量直接影响着顾客的购物体验......
  • 【Java】包装类型变量的形参传递,方法内修改后,方法外还是原值?
    背景前几天有个朋友写代码时,想把int变量作为形参传入方法中进行修改后,在方法外能够获取到修改后的变量进行下一步操作。类似这样:classTest{publicstaticvoidmain(String[]args){intx=1;add(x);System.out.println(x);}pub......
  • PYTHON专题-(4)python叫你搞对象
    什么是面向过程编程?面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数的顺序执行。为了简化程序设计,面向过程把函数继续切分为子函数,即把大块函数通过切割成小块函数来降低系统的复杂度。什么是面向对象编程?面向对象编程——ObjectOrientedProgramming,简......