Proxy request through Apache host to docker container - apache

I have an Ubuntu server host running an Apache web server. Running on this host is a docker container serving Geoserver (via Tomcat) (built from this image) with a port configuration as such: 0.0.0.0:32770->8080/tcp
I can access Geoserver just fine using http://my.domain:32770/geoserver
I have a redirect configured in Apache on the host to serve all requests over HTTPS (see code snippet below), which does not play nicely with the port in requests like this(ie. https://my.domain:32770/geoserver)
<VirtualHost *:80>
# sending http requests to https
ServerName data.nrri.umn.edu
Redirect permanent / https://data.nrri.umn.edu/
</VirtualHost>
My attempt at a workaround for this is to use the ProxyPass directive in an Apache config file:
ProxyRequests Off
ProxyPreserveHost On
ProxyPass /my-geoserver http://127.0.0.1:32770/geoserver
ProxyPassReverse /my-geoserver http://127.0.0.1:32770/geoserver
When I use the URL that I would expect would get me to the Geoserver home page like the one above does (ie. http://my.domain/my-geoserver) I am redirected to
https://my.domain/geoserver/index.html and presented with 404 Not Found.
I should also note that both http://my.domain:32770/geoserver and http://my.domain:32770/geoserver/index.html resolve to http://my.domain:32770/geoserver/web/
What am I doing wrong here?
Edit
Output from curl -L -v -o /dev/null data.nrri.umn.edu/nra-geoserver
* Hostname was NOT found in DNS cache
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying 131.212.123.7...
* Connected to data.nrri.umn.edu (131.212.123.7) port 80 (#0)
> GET /nra-geoserver HTTP/1.1
> User-Agent: curl/7.35.0
> Host: data.nrri.umn.edu
> Accept: */*
>
< HTTP/1.1 302 Found
< Date: Fri, 19 May 2017 15:28:35 GMT
* Server Apache-Coyote/1.1 is not blacklisted
< Server: Apache-Coyote/1.1
< Location: /geoserver/index.html
< Content-Length: 0
< Set-Cookie: JSESSIONID=DFECFFB91353A34C407488EAAF70A2B4; Path=/geoserver; HttpOnly
<
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
* Connection #0 to host data.nrri.umn.edu left intact
* Issue another request to this URL: 'HTTP://data.nrri.umn.edu/geoserver/index.html'
* Found bundle for host data.nrri.umn.edu: 0x95b8c0
* Re-using existing connection! (#0) with host data.nrri.umn.edu
* Connected to data.nrri.umn.edu (131.212.123.7) port 80 (#0)
> GET /geoserver/index.html HTTP/1.1
> User-Agent: curl/7.35.0
> Host: data.nrri.umn.edu
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Date: Fri, 19 May 2017 15:28:35 GMT
* Server Apache/2.4.7 (Ubuntu) is not blacklisted
< Server: Apache/2.4.7 (Ubuntu)
< Location: https://data.nrri.umn.edu/geoserver/index.html
< Content-Length: 336
< Content-Type: text/html; charset=iso-8859-1
<
* Ignoring the response-body
{ [data not shown]
100 336 100 336 0 0 38536 0 --:--:-- --:--:-- --:--:-- 38536
* Connection #0 to host data.nrri.umn.edu left intact
* Issue another request to this URL: 'https://data.nrri.umn.edu/geoserver/index.html'
* Found bundle for host data.nrri.umn.edu: 0x95b8c0
* Hostname was NOT found in DNS cache
* Trying 131.212.123.7...
* Connected to data.nrri.umn.edu (131.212.123.7) port 443 (#1)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
} [data not shown]
* SSLv3, TLS handshake, Server hello (2):
{ [data not shown]
* SSLv3, TLS handshake, CERT (11):
{ [data not shown]
* SSLv3, TLS handshake, Server key exchange (12):
{ [data not shown]
* SSLv3, TLS handshake, Server finished (14):
{ [data not shown]
* SSLv3, TLS handshake, Client key exchange (16):
} [data not shown]
* SSLv3, TLS change cipher, Client hello (1):
} [data not shown]
* SSLv3, TLS handshake, Finished (20):
} [data not shown]
* SSLv3, TLS change cipher, Client hello (1):
{ [data not shown]
* SSLv3, TLS handshake, Finished (20):
{ [data not shown]
* SSL connection using ECDHE-RSA-AES256-GCM-SHA384
* Server certificate:
* subject: C=US; ST=MN; L=Minneapolis; O=University of Minnesota; OU=Natural Resources Research Institute; CN=data.nrri.umn.edu
* start date: 2017-04-18 00:00:00 GMT
* expire date: 2020-04-17 23:59:59 GMT
* subjectAltName: data.nrri.umn.edu matched
* issuer: C=US; ST=MI; L=Ann Arbor; O=Internet2; OU=InCommon; CN=InCommon RSA Server CA
* SSL certificate verify ok.
> GET /geoserver/index.html HTTP/1.1
> User-Agent: curl/7.35.0
> Host: data.nrri.umn.edu
> Accept: */*
>
< HTTP/1.1 404 Not Found
< Date: Fri, 19 May 2017 15:28:35 GMT
* Server Apache/2.4.7 (Ubuntu) is not blacklisted
< Server: Apache/2.4.7 (Ubuntu)
< Content-Length: 301
< Content-Type: text/html; charset=iso-8859-1
<
{ [data not shown]
100 301 100 301 0 0 4404 0 --:--:-- --:--:-- --:--:-- 4404
* Connection #1 to host data.nrri.umn.edu left intact

OK, so there are two redirects happening. I am not sure of a good way to solve the first one (and it is possible the solution solves it as well as the second one). But the second one, you should be able to add a trailing / to the paths. The resulting proxy directives would be:
ProxyPass /my-geoserver/ http://127.0.0.1:32770/geoserver/
ProxyPassReverse /my-geoserver/ http://127.0.0.1:32770/geoserver/
Give this a try first at http://data.nrri.umn.edu/geoserver/index.html and then with http://data.nrri.umn.edu/nra-geoserver and see where it fails next. If the former works but the latter fails, we'll probably need to edit some Tomcat configuration as well (to enable the remote IP valve https://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/valves/RemoteIpValve.html).

Related

Apache HTTP2 h2c mode not working properly

I would like to enable h2c mode on apache, so I can use HTTP2.0 protocol. In my virtual host configuration I have included the line:
Protocols h2c http/1.1
I have also followed the advise to disable prefork but it doesn't work as expected.
Currently I'm using apache 2.4.29 on Ubuntu.
Case 1) curl requesting http2 upgrade
$ curl -vs --http2 http://domain1.com
* Rebuilt URL to: http://domain1.com/
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to domain1.com (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: domain1.com
> User-Agent: curl/7.58.0
> Accept: */*
> Connection: Upgrade, HTTP2-Settings
> Upgrade: h2c
> HTTP2-Settings: AAMAAABkAARAAAAAAAIAAAAA
>
< HTTP/1.1 101 Switching Protocols
< Upgrade: h2c
< Connection: Upgrade
* Received 101
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=28
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
< HTTP/2 200
< date: Sun, 00 Jan 1900 00:00:00 GMT
< server: Apache/2.4.29 (Ubuntu)
< last-modified: Fri, 29 Mar 2019 13:52:29 GMT
< etag: W/"2aa6-5853bfb4c71ac"
< accept-ranges: bytes
< content-length: 10918
< vary: Accept-Encoding
< content-type: text/html
<
.... [snip website code] ....
Case 2) curl directly using http2
$ curl -vs --http2-prior-knowledge http://domain1.com
* Rebuilt URL to: http://domain1.com/
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to domain1.com (127.0.0.1) port 80 (#0)
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x5604f1cb1580)
> GET / HTTP/2
> Host: domain1.com
> User-Agent: curl/7.58.0
> Accept: */*
>
* http2 error: Remote peer returned unexpected data while we expected SETTINGS frame. Perhaps, peer does not support HTTP/2 properly.
As you can see Case 1 is working as expected, but Case 2 is not returning the site. Why is this happening? Is it because Apache is restricting direct use of HTTP2.0 without security?
Hope you can give me an answer as I don't know why things are not working now.
I think I have found the answer, and I think it is a bug in the lastest Apache versions. If I only enable h2c in a virtual host the error persist, but if I enable it on the default virtual host (000-default.conf) everything seems to be working fine.
Another potential solution I have tested and that is working is to enable the protocols h2 and h2c in every virtual host by modifying the mods-enabled/http2.load file:
LoadModule http2_module /usr/lib/apache2/modules/mod_http2.so
<IfModule http2_module>
Protocols h2 h2c http/1.1
</IfModule>
Any of the above mentioned options seems to make the system works as expected both with protocol negotiation and with prior knowledge.

Heroku Hobby Dyno: Error in connection establishment: net::ERR_SSL_PROTOCOL_ERROR, server verification OK but ALPN server does not agree to protocol

I have a simple app where the client is sending a request to join a websocket channel upon page load via a wss connection. I have deployed my app to heroku at domain my_app.heroku.com. Whenever I open my site, I get the error Error in connection establishment: net::ERR_SSL_PROTOCOL_ERROR. I understand that this is an SSL issue, and also that to use Heroku's SSL, you must be on a hobbyist account. So, I upgraded the app to hobbyist (one day ago), but it has not fixed the problem.
I have googled the issue, and from what I see it appears that additional setup beyond upgrading to Heroku Hobby should only be required if using a custom domain-name, which I am not. How can I get the SSL working on my my_app.heroku.com domain with the Hobby dyno?
EDIT: If I run curl -vI <my_app>.heroku_app.com I get the following:
curl -vI https://<my_app>.herokuapp.com
* Rebuilt URL to: https://<my_app>.herokuapp.com/
* Trying __.___.___.___...
* Connected to <my_app>.herokuapp.com (__.___.___.___) port 443
(#0)
* found 148 certificates in /etc/ssl/certs/ca-certificates.crt
* found 592 certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* SSL connection using TLS1.2 / ECDHE_RSA_AES_128_GCM_SHA256
* server certificate verification OK
* server certificate status verification SKIPPED
* common name: *.herokuapp.com (matched)
* server certificate expiration date OK
* server certificate activation date OK
* certificate public key: RSA
* certificate version: #3
* subject: C=US,ST=California,L=San Francisco,O=Heroku\, Inc.,CN=*.herokuapp.com
* start date: Wed, 19 Apr 2017 00:00:00 GMT
* expire date: Mon, 22 Jun 2020 12:00:00 GMT
* issuer: C=US,O=DigiCert Inc,OU=www.digicert.com,CN=DigiCert SHA2
High Assurance Server CA
* compression: NULL
* ALPN, server did not agree to a protocol
> HEAD / HTTP/1.1
> Host: <my_app>.herokuapp.com
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Server: Cowboy
Server: Cowboy
< Connection: keep-alive
Connection: keep-alive
< Content-Type: text/html; charset=utf-8
Content-Type: text/html; charset=utf-8
< Content-Length: 1154
Content-Length: 1154
< Date: Thu, 22 Nov 2018 08:39:51 GMT
Date: Thu, 22 Nov 2018 08:39:51 GMT
< Via: 1.1 vegur
Via: 1.1 vegur
I found the answer after finally finding this question. I thought all along the issue was due to setting up SSL certificates on Heroku, however it was due to my client side code. Per the tutorial I was following, the WS connection was "wss://my_app.herokuapp.com:80/subscribe". Removing the port number was the fix.

Apache Forward Proxy With SSL Termination

I'm trying to set up an Apache Forward Proxy that terminates the SSL connection. The reason I'm trying to do this is to run Apache filters (specifically mod_pagespeed) on the returned code. Before I deal with mod_pagespeed, I'm testing this POC by trying to insert a header into the response (which will prove that I can edit the response), but I'm having issues with SSL proxying (non-SSL proxying works fine).
Note that I'm not concerned about any certificate errors or the like -- this is purely for internal testing.
I've got the server set up and see the X-MSCProxy Header on a non-SSL page:
jshannon-macbookpro:pagespeed_proxy jshannon$ curl -vv --proxy pagespeed_proxy:3ja82ad9#localhost:8080 -D - -o /dev/null http://www.slate.com
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
* Proxy auth using Basic with user 'pagespeed_proxy'
> GET http://www.slate.com/ HTTP/1.1
> Host: www.slate.com
...
>
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Date: Mon, 30 Oct 2017 18:10:40 GMT
Date: Mon, 30 Oct 2017 18:10:40 GMT
< Server: Apache/2.2.29 (Amazon)
Server: Apache/2.2.29 (Amazon)
...
< Content-Length: 187051
Content-Length: 187051
...
< X-Instart-Request-ID: 8286987369135064135:FWP01-NPPRY22:1509387040:0
X-Instart-Request-ID: 8286987369135064135:FWP01-NPPRY22:1509387040:0
< Via: 1.1 172.17.0.2:8080
Via: 1.1 172.17.0.2:8080
< X-MSCProxy: SansPS
X-MSCProxy: SansPS
But when I make the same request to Slate's SSL page I don't see my proxy:
jshannon-macbookpro:pagespeed_proxy jshannon$ curl -vv --proxy pagespeed_proxy:3ja82ad9#localhost:8080 -D - -o /dev/null https://www.slate.com
* Connected to localhost (::1) port 8080 (#0)
* Establish HTTP proxy tunnel to www.slate.com:443
* Proxy auth using Basic with user 'pagespeed_proxy'
> CONNECT www.slate.com:443 HTTP/1.1
> Host: www.slate.com:443
< HTTP/1.0 200 Connection Established
HTTP/1.0 200 Connection Established
< Proxy-agent: Apache/2.4.25 (Debian)
Proxy-agent: Apache/2.4.25 (Debian)
<
* Proxy replied OK to CONNECT request
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate: ssl004.insnw.net
* Server certificate: GlobalSign CloudSSL CA - SHA256 - G3
* Server certificate: GlobalSign Root CA
> GET / HTTP/1.1
> Host: www.slate.com
> User-Agent: curl/7.54.0
> Accept: */*
>
< Content-Length: 187044
Content-Length: 187044
< Connection: keep-alive
Connection: keep-alive
< Server: Apache/2.2.29 (Amazon)
Server: Apache/2.2.29 (Amazon)
< X-Instart-Request-ID: 762420041708891440:FWP01-NPPRY21:1509387251:0
X-Instart-Request-ID: 762420041708891440:FWP01-NPPRY21:1509387251:0
I've found a lot of posts that say this is possible (and, technically, it should be) with various httpd.conf suggestions, but nothing I've tried has worked. Right now my httpd.conf looks like:
<VirtualHost *:8080>
ProxyRequests On
ProxyVia On
Header set X-MSCProxy SansPS
#SSLEngine On
# suggestion that this allows termination
ProxyPreserveHost On
SSLProxyEngine on
SSLProxyCheckPeerCN Off
SSLProxyCheckPeerExpire Off
SSLProxyCheckPeerName Off
SSLCertificateFile /etc/apache2/ssl/localhost.crt
SSLCertificateKeyFile /etc/apache2/ssl/localhost.key
ModPagespeed Off
</VirtualHost>
FWIW, when I enable SSLEngine on this proxy (as has been suggested) then the request simply doesn't work with this error from Apache:
[Mon Oct 30 18:20:20.705047 2017] [ssl:info] [pid 372:tid 140147985901312] [client 172.17.0.1:34012] AH01996: SSL handshake failed: HTTP spoken on HTTPS port; trying to send HTML error page
[Mon Oct 30 18:20:20.705107 2017] [ssl:info] [pid 372:tid 140147985901312] SSL Library Error: error:1407609C:SSL routines:SSL23_GET_CLIENT_HELLO:http request -- speaking HTTP to HTTPS port!?
Which I guess makes sense as the proxy protocol isn't expecting an HTTPS connection directly to the proxy.
I would try to use the output filter feautre fom apache.
https://www.modpagespeed.com/doc/configuration#apache_specific
AddOutputFilterByType MOD_PAGESPEED_OUTPUT_FILTER text/html
Try to add https:// to the curl proxy command like this:
jshannon-macbookpro:pagespeed_proxy jshannon$ curl -vv --proxy https://pagespeed_proxy:3ja82ad9#localhost:8080 -D - -o /dev/null https://www.slate.com
Apache complained about connecting to port 8080 with http even though https is configured for this port.

Heroku ssl certficate not switched with custom domain

I have a heroku app (whatever-app-11123) and I want to use a custom domain through ssl (https://myapp.co).
I have bought the certificate and followed all the instructions provided by heroku.
Strange thing is that https://whatever-app-11123 is displaying the myapp.co certificate and https://myapp.co is displaying the *.herokuapp.com certificate.
I need this to be the other way around : myapp.co with the myapp.co certificat.
Any hints on how achieving this?
Results of different commands :
herok:certs
Endpoint Common Name(s) Expires Trusted
--------------------------------- ---------------------------------------- -------------------- -------
whatever-app-11123.herokuapp.com myapp.co, www.myapp.co 2017-02-12 23:59 UTC True
curl -kvI https://www.myapp.co
* Adding handle: conn: 0x7fbd03804000
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x7fbd03804000) send_pipe: 1, recv_pipe: 0
* About to connect() to www.myapp.co port 443 (#0)
* Trying 46.132.168.142...
* Connected to www.myapp.co (46.132.168.142) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
* Server certificate: *.herokuapp.com
* Server certificate: DigiCert SHA2 High Assurance Server CA
* Server certificate: DigiCert High Assurance EV Root CA
> HEAD / HTTP/1.1
> User-Agent: curl/7.30.0
> Host: www.myapp.co
> Accept: */*
>
< HTTP/1.1 302 Found
HTTP/1.1 302 Found
* Server Cowboy is not blacklisted
<
* Connection #0 to host www.myapp.co left intact
Here's the answer: check your DNS redirection. Make sure it is a CNAME type and MOST OF ALL (what I did wrong) the redirection should be :
www.myapp.co -> whatever-app-11123.herokuapp.com
myapp.co -> whatever-app-11123.herokuapp.com
and not
www.myapp.co -> myapp.co
myapp.co -> whatever-app-11123.herokuapp.com

Golang issue x509: cannot verify signature: algorithm unimplemented on net/http

I was writing a very simple Golang script and use this library golang-jenkins to connect with our internal HTTPS server. But I face the following x509 cert issue and wasn't sure what to do with the x509 cert problem. Our team has zero access to Jenkins and would like to know what else we can do to dig more about the issue.
$ go run jenkins.go
2014/07/28 22:00:29 [] Get https://jenkins.mydomain.com/api/json: x509: certificate signed by unknown authority (possibly because of "x509: cannot verify signature: algorithm unimplemented" while trying to verify candidate authority certificate "MyDomain Internal Root CA")
using curl:
$ curl -v "https://jenkins.mydomain.com/api/json"
* Adding handle: conn: 0x7f8469004000
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x7f8469004000) send_pipe: 1, recv_pipe: 0
* About to connect() to jenkins.mydomain.com port 443 (#0)
* Trying 10.38.8.70...
* Connected to jenkins.mydomain.com (10.38.8.70) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
* Server certificate: jenkins.mydomain.com
* Server certificate: MyDomain Server CA - 2014
* Server certificate: MyDomain Internal Root CA
> GET /api/json HTTP/1.1
> User-Agent: curl/7.30.0
> Host: jenkins.mydomain.com
> Accept: */*
>
< HTTP/1.1 200 OK
* Server nginx is not blacklisted
< Server: nginx
< Date: Tue, 29 Jul 2014 05:03:45 GMT
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Set-Cookie: JSESSIONID.214ca1a4=1ry000odf815goiv7vl8tr627;Path=/;Secure
< Expires: Thu, 01 Jan 1970 00:00:00 GMT
< X-Jenkins: 1.554.3
< X-Jenkins-Session: c660ff91
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 is currently broken in Go, it will be supported in v1.4, the only workaround is to downgrade the TLS MaxVersion.
A quick look at golang-jenkins, it doesn't allow specifying the http.Client to use and just uses http.DefaultClient, the only ugly way to downgrade TLS's MaxVersion is to override http.DefaultClient.Transport.
You should be able to do something like this in func init() before you try to connect to anything:
cfg := &tls.Config{
MaxVersion: tls.VersionTLS11, // try tls.VersionTLS10 if this doesn't work
PreferServerCipherSuites: true,
}
http.DefaultClient.Transport = &http.Transport{
TLSClientConfig: cfg,
}
Keep in mind this will set the transport for anything that uses http.DefaultClient directly, like http.Get, however if you use your own instance, you will be fine.
Discussion about the bug: https://groups.google.com/forum/#!topic/golang-nuts/oK3EBAY2Uig