Setting up https on a server with Phoenix/Elixir and nginx - ssl

I know how to setup https for, say, clojure web app with nginx. How to do that for Phoenix?
In the prod.exs I have this:
config :my_app, MyApp.Endpoint,
url: [host: "my_website.com", port: 443],
http: [port: 4000],
# https: [port: 443,
# keyfile: System.get_env("SOME_APP_SSL_KEY_PATH"),
# certfile: System.get_env("SOME_APP_SSL_CERT_PATH")],
cache_static_manifest: "priv/static/manifest.json"
I have this:
ssl_certificate: /etc/letsencrypt/live/my_app.com/fullchain.pem;
ssl_certificate_key: /etc/letsencrypt/live/my_app.com/privkey.pem;
I want to use nginx with Phoenix as well.
1) Should I remove "http: [port: 4000]," compeletely from "prod.exs"?
2) Should I instead uncomment "https: [port: 443,...." ? Or should I have them both? I don't want to website to be accessible at http or I'd let nginx take care of it by redirecting a user from http to https.
3) Or should I remove https and http and let nginx handle that?
4) How about the key "url" and its "port"?

If you are using Nginx to terminate the SSL part of the connection, then you leave the app server configured for HTTP and any port you like (4000 is fine as long as you configure Nginx to forward to it). If your server is configured correctly, it will not answer HTTP port 4000 requests, thus the SSL cannot be bypassed.
The SSL configuration you are referring to at the app server level configures the app server to terminate the SSL connection (no Nginx necessary). Phoenix apps are all "full featured" web servers thanks to cowboy. Thus, they can handle the SSL termination as well as serving the application's dynamic and static assets.
The URL configuration is so your application knows its domain and can generate full urls as well as paths.

If you're set on using nginx in front of your Phoenix app then use nginx to terminate the ssl connection (your option 3). You still need to configure http in Phoenix though since nginx will proxy to your app using http. Therefore:
config :my_app, MyApp.Endpoint,
url: [host: "my_website.com", port: 4000],
http: [port: 4000]
Which assumes you will configure nginx to proxy to your app on port 4000. You will also want to adjust the host config key to be the base url of your site since any URL's you generate will use this base name (as Jason mentioned).

Related

Use Apache as Forward Proxy in a Proxy Chain including Proxy Authentication

I'm building a proxy chain to access an internal proxy from the outside with additional authentication:
Internet -> [Apache Forward Proxy] -> [Internal Squid Proxy] -> Internal Website
The Apache Forward Proxy is doing TLS including Certificate Based Authentication (CBA), the Squid Proxy requires basic auth with username / password. Authentication works as expected for both components.
Challenge is now to get the Apache to act as a Forward Proxy and to forward the Proxy-Authorization header from the user to the internal Proxy.
Here is the current configuration I'm using (mod_proxy and mod_proxy_connect are enabled):
# Enable forward proxy
ProxyRequests On
# Pass all requests on to the squid proxy
ProxyRemote * http://proxy.internal:3128
# Only allow proxy connect to port 443
AllowCONNECT 443
With this setup the Apache doesn't forward the Proxy-Authorization header to the internal proxy. All settings I could find for this topic (Proxy-Chain-Auth, ProxyAddHeaders, rewrite rules etc.) only work in Reverse Proxy mode using ProxyPass. But a Reverse Proxy doesn't fit here since in this mode the Apache modifies the header and the CONNECT for TLS webservers won't work.
The Apache doesn't forward any header fields from the client, in the end a request from the Apache to the internal Proxy looks like this:
CONNECT someserver.de:443 HTTP/1.0\r\n
Proxy-agent: Apache/2.4.18 (Ubuntu)\r\n
\r\n
I'm aware the Proxy-Authorization field is a Hop-by-hop field which is normally not allowed to passed to the next proxy.
Is it still possible to get the Apache to forward a Proxy-Authorization header to the internal Proxy when acting as Forward Proxy?
There is a bug for a related topic in the Apache bugtracker. But this one is to specify the username/password hard-coded in the apache config which is not what I need. I want to forward the client authorization individually.
https://bz.apache.org/bugzilla/show_bug.cgi?id=37355

HTTPS proxy with caddy

I am working with a Golang app and Caddy as the HTTP server. The golang app rejects every http connection, it only can be used over HTTPS. This app is a kind of API/service that is consumed by other apps. As, it requires HTTPS I installed Caddy so I can take advantage of the automatic SSL certificate and use proxy to switch between the ports.
The application is running in the port 9000, so, the consumers will only writte mysite.com and caddy should be in charge of redirect that petitions to the port 9000 but maintaining the HTTPS. The configuration in caddy for the site is:
mysite.com {
proxy / :9000 {
max_fails 1
}
log logfile
}
Nevertheless, it seems like when the proxy is made the HTTPS is lost. I checked the logs for the application (no the logs of caddy) and I get this:
http: TLS handshake error from xxx.xxx.xxx.xxx:xxxx: tls: oversized record received with length 21536
So, based in this error, to me looks like the HTTP proxy made by caddy is losing the HTTPS. What can I do?
From the caddy docs
to is the destination endpoint to proxy to. At least one is required,
but multiple may be specified. If a scheme (http/https) is not
specified, http is used. Unix sockets may also be used by prefixing
"unix:".
So maybe it is sending http requests to the proxied https endpoint.
Does
mysite.com {
proxy / https://localhost:9000 {
max_fails 1
}
log logfile
}
fix it?
If that is the case, you may not strictly need your app on :9000 to listen https. It may simplify your deployment or cert management to just have it listen http and have caddy manage all the certs.

WSGI with SSL behind NGINX

currently I want to deploy my pyramid application on a server. Therefore I'am using NGINX in front of WSGI. There is no problem to configure SSL in NGINX, but for WSGI it is.
Because I have port-forwarding from 80 to 443, the user receives an:
Mixed Content: The page at 'https://example.com' was loaded over HTTPS, but requested an insecure stylesheet 'http://example.com/static/css/bootstrap-3.3.5.min.css'. This request has been blocked; the content must be served over HTTPS.
How can I enable SSL for WSGI?
Thx
Thanks to I can not connect to https waitress wsgi server i found the solution. Just add "url_scheme = https" to your production.ini / development.ini.

SSL on application in nginx

I am running an nginx web server where I redirect all http requests to https (with a self signed cert).
Problem is - I cannot seem to do so for an app running on a port. Example:
http://my.server.ip:1234
How can I modify the nginx config file to force that url through ssl?
try this:
return 301 https://my.server.ip:1234$request_uri;

Is it possible to have a forward proxy with ssl encryption between the proxy and the user?

First of all I want to make clear that i am not talking about accessing content which is on origin servers that deliver using https which can be done using the module mod_proxy_connect.
What I want is a secured connection between the client and the proxy, also when the origin that is requested actually is served by an unsecured standard http server.
I am using apache 2.2 and also would like to make this possible with apache if that works.
I sniffed some requests using wireshark and noted the following:
A usual http of the url http://example.com/file looksl ike this:
on a connection to the origin server:
GET /file HTTP 1.1
Host: example.com
Note that the host information is stripped from the actual request and the host header is supplied instead (which can be handled server side in named virtual hosts).
When the request goes through a proxy server it looks slightly different:
on a connection to the proxy server:
GET http://example.com/file HTTP 1.1
Host: example.com
Note that the request line now actually contains the full url including protocol and hostname.
The host header is probably redundant, bus if I read the RFC correctly it is required by HTTP 1.1.
So I think about setting up an apache webserver listening on port 443, enable a virtualhost with ssl engine and certificates up and do not bind it to any hostname.
I think that should get apache to talk ssl, but however the certificates common name will not match the host specfied in the connect line to the proxys server ip adress.
Is what I want to to even possible with current standards and if so how can I do it?
Yes of course, that's what HTTPS proxy is.
Client connects to proxy over SSL, sends commands to proxy in text.
It is also possible to use HTTP CONNECT to establish HTTPS connection "inside" the SSL connection to HTTPS proxy, though not all clients support this:
HTTPS connection over HTTPS proxy
client proxy server
ssl \-------/ ssl
connect---------200 OK
ssl \---------------------------/ ssl
data-------------------------------data
/---------------------------\
/-------\
HTTP connection over HTTPS proxy
client proxy server
ssl \-------/ ssl
GET http://server/ ->
GET /
Host: server ->
<---------OK, data
<--------------OK, data
/-------\