4

I am using Docker to setup my Python environment. For, that I am using the python:3.6-slim base image.

I need to now send a get request to a URL which is only available in the intranet (let's assume it's https://internal.company.com/API/some_value). I am using a Ubuntu server on AWS EC2, where I am trying to build this image.

From that EC2 server, I am able to request the above URL, but, when I do the same from inside the docker container, I get the following error.

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 672, in urlopen
    chunked=chunked,
  File "/usr/local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 376, in _make_request
    self._validate_conn(conn)
  File "/usr/local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 994, in _validate_conn
    conn.connect()
  File "/usr/local/lib/python3.6/site-packages/urllib3/connection.py", line 394, in connect
    ssl_context=context,
  File "/usr/local/lib/python3.6/site-packages/urllib3/util/ssl_.py", line 370, in ssl_wrap_socket
    return context.wrap_socket(sock, server_hostname=server_hostname)
  File "/usr/local/lib/python3.6/ssl.py", line 407, in wrap_socket
    _context=self, _session=session)
  File "/usr/local/lib/python3.6/ssl.py", line 817, in __init__
    self.do_handshake()
  File "/usr/local/lib/python3.6/ssl.py", line 1077, in do_handshake
    self._sslobj.do_handshake()
  File "/usr/local/lib/python3.6/ssl.py", line 689, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [SSL: UNSUPPORTED_PROTOCOL] unsupported protocol (_ssl.c:852)

NOTE: I am able to request other https website from within the container. It's possible that the SSL protocol used in the internal URL might be different from the websites used on the internet, and I don't have any way of knowing what.

Following is my Dockerfile. Do I need to install any othe packages to support this?

FROM python:3.6-slim
WORKDIR /app
RUN apt-get -y update \
    && apt-get -y upgrade \
    && apt-get install -y poppler-utils \
    && apt-get install -y libsm6 libxext6 libxrender-dev libglib2.0-0

ARG DEBIAN_FRONTEND=noninteractive

RUN apt-get install -y postgresql

COPY dlib-19.17.0-cp36-cp36m-linux_x86_64.whl /app/dlib-19.17.0-cp36-cp36m-linux_x86_64.whl
COPY requirements.txt /app/requirements.txt

RUN pip3 install dlib-19.17.0-cp36-cp36m-linux_x86_64.whl \
    && pip3 install -r requirements.txt

COPY . /app

CMD gunicorn -t 300 --workers 5 --bind  0.0.0.0:8080 wsgi

I am using requests library to send the GET request

import requests as r

response = r.get('https://internal.company.com/API/some_value')
print(response)
Parthapratim Neog
  • 4,352
  • 6
  • 43
  • 79

2 Answers2

7

Probably your server is exposing an old, insecure version of the TLS protocol, which modern OpenSSLs are configured not to allow.

https://stackoverflow.com/a/53065682/6214034 might help.

EDIT 2021:

Let me summarize what you have in the comments for those who are lazy to read them...

You have to change the entry MinProtocol from TLSv1.2 to TLSv1.0 in the /etc/ssl/openssl.cnf

To replace that line, you can add RUN sed -i -E 's/MinProtocol[=\ ]+.*/MinProtocol = TLSv1.0/g' /etc/ssl/openssl.cnf to your Dockerfile

Espoir Murhabazi
  • 5,973
  • 5
  • 42
  • 73
Itamar Turner-Trauring
  • 3,430
  • 1
  • 13
  • 17
1

Be careful at setting minimum version system-wide, it's more secure to setup it in your script by own HTTPAdapter:

import ssl
ssl_context = ssl.create_default_context()
# Sets up old and insecure TLSv1.
ssl_context.options &= (
    ~getattr(ssl, "OP_NO_TLSv1_3", 0)
    & ~ssl.OP_NO_TLSv1_2
    & ~ssl.OP_NO_TLSv1_1
)
ssl_context.minimum_version = ssl.TLSVersion.TLSv1
frost-nzcr4
  • 1,540
  • 11
  • 16
  • Many linters report there is no ssl.OP_NO_TLSv1_3 so I've replaced it to `getattr(ssl, "OP_NO_TLSv1_3", 0)` and updated the answer. – frost-nzcr4 Oct 16 '20 at 08:03