check_docker icon indicating copy to clipboard operation
check_docker copied to clipboard

How to do version checks through a proxy server

Open HigH-HawK opened this issue 5 years ago • 4 comments

Hi @timdaman

Everything is working fine so far and I am currently trying to add a few more checks to monitor the Docker containers properly.

I noticed the "--version" check and thought, that this check would check the current version, if so I would certainly like to have this feature implemented in my monitoring, so I can keep track of the current version or get notified as soon as there is a new version.

I seem to however have problems getting this to work, due to our servers working behind a proxy server. The main message appearing is "connection refused" which gave me the hint, that the "check_docker version check" script cannot communicate with the registry server due to the proxy server blocking it.

Would there be a possibility to add a proxy option to the command line, so that people with a proxy server can add their IP/FQDN:Port in the query?

Example: --proxy IP/FQDN:Port

I had a look at your code but my last Python coding lies quite a bit back, so I could only achieve to add a new function would not know where to change the actual query.

If you could implement this feature I would be more than happy to test this for you.

HigH-HawK avatar Jan 21 '19 09:01 HigH-HawK

I am open minded to that but I don't have a suitable test environment to support it. In-fact I have never had to use a proxy (lucky me). If you can help me design a simulation of such a thing that would be a great help.

There are two basic groupings of network connections in check_docker

  1. Connections to docker hosts
  2. Registries which may be internal or external

I assume we can ignore #1 given your question. As for #2 however, we may have images from multiple registries only some of which may need a proxy.

So I dug into this and have a bunch of thoughts and questions (in nor particular order).

  • The network library I am using, urllib, has something called ProxyHandler that appears to do this. It can be configured directly but also it will look at the current environment variables to find configure itself.
  • A question, how do proxies handle internal traffic. If I send everything to the proxy will it bounce the internal traffic back to the internal network? If it doesn't do this then we will have to support configuring proxy on a per-domain basis.

I can add the Proxy handler pretty easily if you want see if works for you.

timdaman avatar Mar 17 '19 00:03 timdaman

Hey, thanks for coming back to me.

I had a look myself but as i said, my programming days are a while back. The ProxyHandler from urllib is suppose to check environment variables for the proxy information (if there are any) but it doesn't seem to do that properly because I have my proxy information in the environment variables (HTTP_PROXY, HTTPS_PROXY, http_proxy, https_proxy).

As for the internal/external traffic, our proxy is setup to handle only external traffic, internal traffic is not being touched by it, as far as I know.

It would be great if you could add the ProxyHandler and I would be happy to test it and report back to you.

HigH-HawK avatar Mar 18 '19 09:03 HigH-HawK

I have created a branch for this proxy work, https://github.com/timdaman/check_docker/tree/proxy

Here is a direct link to a check_docker.py with the ProxyHandler enabled. https://github.com/timdaman/check_docker/raw/proxy/check_docker/check_docker.py

Hope it works.

timdaman avatar Mar 19 '19 02:03 timdaman

Hi Tim,

I could now test the new check_docker file but am still getting an error:

Command: ./check_docker --containers redmine --version

Error output:

Traceback (most recent call last):
  File "/usr/lib64/python3.6/urllib/request.py", line 1318, in do_open
    encode_chunked=req.has_header('Transfer-encoding'))
  File "/usr/lib64/python3.6/http/client.py", line 1239, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/lib64/python3.6/http/client.py", line 1285, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/lib64/python3.6/http/client.py", line 1234, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/lib64/python3.6/http/client.py", line 1026, in _send_output
    self.send(msg)
  File "/usr/lib64/python3.6/http/client.py", line 964, in send
    self.connect()
  File "/usr/lib64/python3.6/http/client.py", line 1392, in connect
    super().connect()
  File "/usr/lib64/python3.6/http/client.py", line 936, in connect
    (self.host,self.port), self.timeout, self.source_address)
  File "/usr/lib64/python3.6/socket.py", line 724, in create_connection
    raise err
  File "/usr/lib64/python3.6/socket.py", line 713, in create_connection
    sock.connect(sa)
ConnectionRefusedError: [Errno 111] Connection refused

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "./check_docker", line 1004, in main
    [x.result() for x in futures.as_completed(threads)]
  File "./check_docker", line 1004, in <listcomp>
    [x.result() for x in futures.as_completed(threads)]
  File "/usr/lib64/python3.6/concurrent/futures/_base.py", line 425, in result
    return self.__get_result()
  File "/usr/lib64/python3.6/concurrent/futures/_base.py", line 384, in __get_result
    raise self._exception
  File "/usr/lib64/python3.6/concurrent/futures/thread.py", line 56, in run
    result = self.fn(*self.args, **self.kwargs)
  File "./check_docker", line 654, in check_version
    raise e
  File "./check_docker", line 642, in check_version
    registry_hash = get_digest_from_registry(url)
  File "./check_docker", line 393, in get_digest_from_registry
    registry_info = head_url(url=url)
  File "./check_docker", line 292, in head_url
    response = better_urllib_get.open(HeadRequest(url), timeout=timeout)
  File "/usr/lib64/python3.6/urllib/request.py", line 526, in open
    response = self._open(req, data)
  File "/usr/lib64/python3.6/urllib/request.py", line 544, in _open
    '_open', req)
  File "/usr/lib64/python3.6/urllib/request.py", line 504, in _call_chain
    result = func(*args)
  File "/usr/lib64/python3.6/urllib/request.py", line 1361, in https_open
    context=self._context, check_hostname=self._check_hostname)
  File "/usr/lib64/python3.6/urllib/request.py", line 1320, in do_open
    raise URLError(err)
urllib.error.URLError: <urlopen error [Errno 111] Connection refused>
UNKNOWN: Exception raised during check': URLError(ConnectionRefusedError(111, 'Connection refused'),)

I did check whether my proxy server is set in env:

env | grep -i proxy

And I do get http_proxy, HTTP_PROXY, https_proxy, HTTPS_PROXY back with the proxy address.

HigH-HawK avatar Mar 21 '19 09:03 HigH-HawK