RHEL Engineering is moving the tracking of its product development work on RHEL 6 through RHEL 9 to Red Hat Jira (issues.redhat.com). If you're a Red Hat customer, please continue to file support cases via the Red Hat customer portal. If you're not, please head to the "RHEL project" in Red Hat Jira and file new tickets here. Individual Bugzilla bugs in the statuses "NEW", "ASSIGNED", and "POST" are being migrated throughout September 2023. Bugs of Red Hat partners with an assigned Engineering Partner Manager (EPM) are migrated in late September as per pre-agreed dates. Bugs against components "kernel", "kernel-rt", and "kpatch" are only migrated if still in "NEW" or "ASSIGNED". If you cannot log in to RH Jira, please consult article #7032570. That failing, please send an e-mail to the RH Jira admins at rh-issues@redhat.com to troubleshoot your issue as a user management inquiry. The email creates a ServiceNow ticket with Red Hat. Individual Bugzilla bugs that are migrated will be moved to status "CLOSED", resolution "MIGRATED", and set with "MigratedToJIRA" in "Keywords". The link to the successor Jira issue will be found under "Links", have a little "two-footprint" icon next to it, and direct you to the "RHEL project" in Red Hat Jira (issue links are of type "https://issues.redhat.com/browse/RHEL-XXXX", where "X" is a digit). This same link will be available in a blue banner at the top of the page informing you that that bug has been migrated.
Bug 1434876 - subscription-manager does not work behind cascaded proxies
Summary: subscription-manager does not work behind cascaded proxies
Keywords:
Status: CLOSED WONTFIX
Alias: None
Product: Red Hat Enterprise Linux 7
Classification: Red Hat
Component: subscription-manager
Version: 7.3
Hardware: Unspecified
OS: Linux
medium
medium
Target Milestone: rc
: 7.3
Assignee: candlepin-bugs
QA Contact: John Sefler
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2017-03-22 14:25 UTC by Akash
Modified: 2023-09-14 03:55 UTC (History)
5 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2017-04-23 21:30:00 UTC
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Red Hat Bugzilla 1435331 0 low CLOSED Host header set improperly when configured with a proxy 2021-02-22 00:41:40 UTC
Red Hat Bugzilla 1451166 0 high CLOSED Incorrect "Host" header when connecting through a http proxy 2021-02-22 00:41:40 UTC

Internal Links: 1435331 1451166

Description Akash 2017-03-22 14:25:17 UTC
Description of problem:
subscription-manager talks to internal HTTP(s) proxy. subscription-manager uses, as it always does, TLS client cert authentication. subscription-manager also performs certificate validation. Customer is intercepting proxy re-encrypts the traffic. Therefore, subscription-manager is configured to check the provided server certificate against our site CA instead of Red Hat certificate.

Customer proxy server is configured to accept Red Hat's own CA for the relevant RHSM hostnames and does not perform the usual Browser-like public CA validation, but validates only this single CA. Also, our proxy is provided with the necessary client certificate.

Therefore, when a client (subscription-manager) contacts the proxy, the proxy will verify that the client possesses the proper certificate. If it does, then the proxy will authenticate to RHSM using its own copy of the client certificate. 

How reproducible:
100% reproducible

Steps to Reproduce:
- yum install subscription-manager squid httpd mod_ssl
- make apache return HTTP 403:
  echo $'<Location />\nDeny from all\n</Location>\n' > /etc/httpd/conf.d/welcome.conf
- configure subscription-manager to use this setup instead of RHN
        # subscription-manager config --server.hostname=127.0.0.99
        # subscription-manager config --server.proxy_hostname=127.0.0.11
        # subscription-manager config --server.proxy_port=3128
        # subscription-manager config --server.insecure=1
- watch it fail
        # subscription-manager register  --user foo --password bar
        Registering to: 127.0.0.99:443/subscription
        Forbidden: Invalid credentials for request.

- further details can be analyzed with the following hack:
  by adding 'print data' to /usr/lib64/python2.7/site-packages/M2Crypto/SSL/Connection.py:221
  we can intercept the unencrypted HTTP traffic:

       GET /subscription/users/foo/owners HTTP/1.1
        Host: 127.0.0.11:3128
        Accept-Encoding: identity
        Content-Length: 0
        Accept-Language: en-us
        x-subscription-manager-version: 1.17.15-1.el7.centos
        x-python-rhsm-version: 1.17.9-1.el7
        Accept: application/json
        User-Agent: RHSM/1.0 (cmd=subscription-manager)
        Content-type: application/json
        Authorization: Basic Zm9vOmJhcg==

This shows that the request contains a Host: header with the proxy's name/address.
  At this place, the hostname of the target address is (127.0.0.99 ) is
  supposed to show up.

  I assume that this issue technically affects all customers using subscription-manager.
  However, when there is only one proxy in-between, the only side effect will be that
  you will see unexpected Host: headers on the web server at subscription.rhsm.redhat.com.
  In other words, this would break for all proxy-using customers if you decided to enable named-based
  virtual hosting on this server.

  Here, subscription-manager will send a CONNECT verb to our first proxy and will embed the above-cited request.
  First proxy is configured to send the request to a second proxy for content security reasons.
  Customer assume that at least one of these proxies has to rely on the request to contain a proper Host: statement.
  However, the request generated by subscription-manager does not contain a sane Host: header.
  Therefore, the request ends up being served (instead of forwarded) by our proxy. The proxy will of course
  refuse this request with HTTP status code 403. This leads to subscription-manager exiting with an error.

  Due to this bug, Customer is unable to use subscription-manager with RHN.

  Customer believes that there are two code issues:
  (1) The invoking code in rhsm.connection only sometimes adds a (correct) Host: header. For example, when running
  'subscription-manager register', no Host: header is added.
  This part could probably be fixed as part of the subscription-manager / python rhsm package.

  (2) In any case, some code in-between (I assume M2Crypto httplib wrapping code) always adds a wrong Host: header
  containing the address of the used proxy.
  This part would probably need a change in M2Crypto.

Actual results:
Peer's Certificate issuer is not recognized"

Expected results:
Systems should be able to get registered without any issues

Additional info:
Adding a pdb breakpoint will show that the actual introduction of the Host: header happens in python's standard httplib:

# subscription-manager register  --user foo --password bar
Registering to: 127.0.0.99:443/subscription
> /usr/lib64/python2.7/site-packages/M2Crypto/httpslib.py(179)putheader()
-> if header.lower() == self._UA_HEADER.lower():
(Pdb) print header, value
Host 127.0.0.11:3128
(Pdb) bt
  /usr/sbin/subscription-manager(81)<module>()
-> sys.exit(abs(main() or 0))
  /usr/sbin/subscription-manager(72)main()
-> return managercli.ManagerCLI().main()
  /usr/lib/python2.7/site-packages/subscription_manager/managercli.py(2744)main()
-> return CLI.main(self)
  /usr/lib/python2.7/site-packages/subscription_manager/cli.py(160)main()
-> return cmd.main()
  /usr/lib/python2.7/site-packages/subscription_manager/managercli.py(526)main()
-> return_code = self._do_command()
  /usr/lib/python2.7/site-packages/subscription_manager/managercli.py(1126)_do_command()
-> owner_key = self._determine_owner_key(admin_cp)
  /usr/lib/python2.7/site-packages/subscription_manager/managercli.py(1271)_determine_owner_key()
-> owners = cp.getOwnerList(self.username)
  /usr/lib64/python2.7/site-packages/rhsm/connection.py(1126)getOwnerList()
-> return self.conn.request_get(method)
  /usr/lib64/python2.7/site-packages/rhsm/connection.py(694)request_get()
-> return self._request("GET", method)
  /usr/lib64/python2.7/site-packages/rhsm/connection.py(584)_request()
-> conn.request(request_type, handler, body=body, headers=headers)
  /usr/lib64/python2.7/httplib.py(973)request()
-> self._send_request(method, url, body, headers)
  /usr/lib64/python2.7/httplib.py(1001)_send_request()
-> self.putrequest(method, url, **skips)
  /usr/lib64/python2.7/site-packages/M2Crypto/httpslib.py(174)putrequest()
-> HTTPSConnection.putrequest(self, method, rest, skip_host, skip_accept_encoding)
  /usr/lib64/python2.7/httplib.py(920)putrequest()
-> self.putheader('Host', "%s:%s" % (host_enc, self.port))
> /usr/lib64/python2.7/site-packages/M2Crypto/httpslib.py(179)putheader()
-> if header.lower() == self._UA_HEADER.lower():
(Pdb)

When simulation the subscription-manager HTTP traffic using curl, everything works as expected,
as curl adds the correct Host: header.

The following patch makes the subscription-manager register call succeed against RHN.
I believe that it might have unwanted side-effects for other M2Crypto user.
The proper fix might have to be done in some subscription-manager-specific
code path.

--- /usr/lib64/python2.7/site-packages/M2Crypto/httpslib.py.orig        2017-02-01 22:54:55.827000000 +0100
+++ /usr/lib64/python2.7/site-packages/M2Crypto/httpslib.py     2017-02-01 22:55:31.089000000 +0100
@@ -142,7 +142,7 @@
         self._proxy_auth = None
         self._proxy_UA = None

-    def putrequest(self, method, url, skip_host=0, skip_accept_encoding=0):
+    def putrequest(self, method, url, skip_host=1, skip_accept_encoding=0):
         #putrequest is called before connect, so can interpret url and get
         #real host/port to be used to make CONNECT request to proxy
         proto, netloc, path, query, fragment = urlsplit(url)
@@ -172,6 +172,7 @@
             HTTPSConnection.putrequest(self, method, rest, skip_host)
         else:
             HTTPSConnection.putrequest(self, method, rest, skip_host, skip_accept_encoding)
+       self.putheader('Host', netloc)

     def putheader(self, header, value):
         # Store the auth header if passed in.

Customer have resolved all certificate-related issues in our real-world setup (or rather, our Proxy Team has). Customer's setup uses features which are officially provided by our Proxy vendor.

Basically, subscription-manager talks to our internal HTTP(s) proxy. subscription-manager uses, as it always does, TLS client cert authentication. subscription-manager also performs certificate validation. In our case, our intercepting proxy re-encrypts the traffic. Therefore, subscription-manager is configured to check the provided server certificate against our site CA instead of Red Hat's.
Customer's proxy server is configured to accept Red Hat's own CA für the relevant RHSM hostnames and does not perform the usual Browser-like public CA validation, but validates only this single CA. Also, our proxy is provided with the necessary client certificate.
Therefore, when a client (subscription-manager) contacts the proxy, the proxy will verify that the client possesses the proper certificate. If it does, then the proxy will authenticate to RHSM using its own copy of the client certificate.
All in all, everything TLS-related works.

Our issue is that subscription-manager generates semantically invalid HTTP requests, which are sent using this TLS connection. The wrong content (more specific, the wrong Host: header) makes it impossible for a proxy to forward the request to the correct destination (RHSM). Instead, the request ends up being targeted at our proxy itself!

Comment 2 Kevin Howell 2017-03-23 14:44:58 UTC
We will take a look at the Host header, and try to fix any bad behavior on the behalf of subscription-manager.

It is worth noting that as of RHEL 7.4, the HTTPs functionality will be using python standard libraries, and not M2Crypto, so the behavior may change (hopefully for the better :-)) Though RHEL 6.* still uses M2Crypto.

However, the use case described is not one that we can support, because, there are multiple client certificates at play for a given system (ex. client ID cert to RHSM, entitlement certs for CDN access), and these are unique for each system. If the proxy is configured to terminate SSL and is configured to use one of these certificates, it will appear to RHSM as if one system is connecting, rather than the full number of systems behind the proxy, and consequently rate limiting will happen.

There are other considerations that are difficult to address (ex. rhsmcertd on the system will update these certificates as necessary), which complicates trying to keep a proxy configured with the right certificates.

Comment 9 Red Hat Bugzilla 2023-09-14 03:55:26 UTC
The needinfo request[s] on this closed bug have been removed as they have been unresolved for 1000 days


Note You need to log in before you can comment on or make changes to this bug.