当我尝试访问GeoPy API时,在AWS EC2实例上获取SSL错误



我正在尝试连接到Nomatim GeoPy API,以从邮政编码中解析纬度/经度坐标。实现如下(最低可重复性):

# Create a function that returns lat/lon coordinates from zip code
def get_coord(zip_code):
geolocator = Nominatim(user_agent="GCD Data Client")
location = geolocator.geocode({"postalcode": zip_code, "country": "US"}, exactly_one = True)
in_lat = location.latitude
in_lon = location.longitude
return in_lat, in_lon
# Inputs for data
def get_params(self, zip_code):
# Do error checking to prevent strange, unexpected output from leaving function
out = False
while not out:
try:
in_lat, in_lon = get_coord(zip_code)
# Make sure the lat/lon pair is valid
if abs(in_lat) > 90 or abs(in_lon) > 180:
raise ValueError
out = True
except ValueError:
print("Make sure your lat/lon coordinates are valid (-90-90, -180-180)")
return in_lat, in_lon
if __name__ == '__main__':
# Get some input lats and lons
in_lats = []
in_lons = []
zip_codes = [14201, 80919, 84101] # Dummy data
for zip_code in zip_codes:
in_lat, in_lon = get_params(zip_code)
in_lats.append(in_lat)
in_lons.append(in_lon)
print(in_lats)
print(in_lons)

然而,代码不是问题所在。当我在本地机器(windows)上运行这段代码时,我会得到预期的lat/lon坐标。我敢肯定,问题是与GeoPy服务器的通信被AWS阻止了,因为我在那里运行时遇到了这个错误:

geopy.exc.GeocoderUnavailable: HTTPSConnectionPool(host='nominatim.openstreetmap.org', port=443): Max retries exceeded with url: /search?postalcode=14201&country=US&format=json&limit=1 (Caused by SSLError(SSLError("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",),))

我尝试了一些不同的ec2安全配置。一个使用默认的SSH和HTTPS(因为443路由到的是HTTPS)。我还尝试将它开放给所有入站流量(尽管这是一种糟糕的安全做法)进行测试,因为它只是一个开发服务器(此后再次锁定:))。在这两种情况下,我仍然有同样的问题。这是我需要以某种方式启用的SSL设置吗?

我尝试过,我可以确认这不是与ec2相关的问题,因为我在ec2上尝试过,它有效。

简而言之,您可能需要使用最新的python版本或更改系统证书文件。

这是我2021年的测试结果:在我的环境中,python 3.6.8+geopy 2.2.0+centos 7作品;python 2.7.18+geopy 1.23.0+centros 8也可以;但python2.7.5+geopy1.23.0+centros7不起作用,并报告证书错误。

最后,我找到了根本原因,这是由于LetsCrypt使用的旧的"DST"根证书于9月30日到期;看见https://letsencrypt.org/docs/dst-root-ca-x3-expiration-september-2021。如果Python使用1.1.0以下的OpenSSL,则会受到影响;看见https://openssl.org/blog/blog/2021/09/13/LetsEncryptRootCertExpire.

我让python 2.7.5+geopy 1.23.0+centros 7+openssl 1.0.2k-fips与变通方法1一起工作,即从系统证书中删除(DST Root CA X3)根证书,详细步骤为:

  1. 检查DST根是否在/etc/pki/tls/certs/ca-bundle.crt和ISRG根中X1在ISRG根X1中
  2. 复制"#DST根CA X3";进入的部分/etc/pki/ca信任/source/黑名单目录作为pem文件
  3. 运行更新ca信任
  4. 检查DST根不再在/etc/pki/tls/certs/ca-bundle.crt,并且ISRG根X1在ISRG Root中X1

参考:

  • https://github.com/geopy/geopy/issues/124
  • Mongodb SSL连接使用Let's encrypt颁发的SSL证书时失败即使证书没有过期