I have configured below rule in HA Proxy. I get 404 not found when I try to hit http://haproxy_ip/service
frontend http-in
bind 10.254.23.225:80
acl has_service path_beg /service
use_backend service_server if has_service
backend service_server
balance roundrobin
cookie SERVERID insert
option httpchk HEAD /check.txt HTTP/1.0
option httpclose
option forwardfor
server server1 192.168.2.1:9000 cookie server1 check
backend doesnt have /service in itself. I use haproxy to have virutal path in url.
With the current configuration, /service/test.txt will trigger the acl has_service and will send /service/test.txt to your backend, without changing the url.
If you want to change the url (proxying /service in the frontend to / in the backend), you should add the following line in your backend:
reqrep ^([^\ ]*)\ /service(.*) \1\ \2
This will remove /service from the proxied request.
Edit:
HAProxy won't rewrite the html output: your assets won't get a leading /service/ and won't be served correctly.
When you proxy requests, it is way easier to keep the same path: proxying / to / or /myapp/ to /myapp/ for example. If you proxy /a to /b/c, the proxy itself will need to rewrite the response: <img src="/a/test.png"> needs to be changed to <img src="/b/c/test.png">. Or worse, <img src="../c/test.png" />. Add relative references in html, js and css too. I'm not sure it's doable with HAProxy.
If you can change the application and deploy it on /service/, you will avoid a lot of issues. Using an other vhost (service.yourdomain.com for example) can solve this issue too.
If not, I'm not sure HAProxy is the right tool here, I'd try apache 2.4 with
mod_proxy_html (but not before trying really hard to deploy the app on /service/).
Related
I need to deploy different apps on the same domain, thus I've set up the backend to rewrite URL with reqrep ^([^\ ]*\ /)appA[/]?(.*) \1\2. It works when I only deploy the HTTP or HTTPS version of the app.
However, if I try to redirect all HTTP traffic to HTTPS, it doesn't work. The problem is that HAProxy has already rewritten the URL and stripped out the /appA part before the redirection. Thus if I try to visit http://myserver.com/appA, the page https://myserver.com will eventually be requested instead of https://myserver.com/appA.
I can't put the redirect rule before the reqrep rule as it seems that HAProxy must process all the rewrites before the redirects.
What can I do to make my configuration work as I intended? This should be obvious but I can't seem to find a relevant answer online.
My configuration:
frontend http_front
bind *:80
reqadd X-Forwarded-Proto:\ http
acl appA_url url_beg /appA
use_backend appA if appA_url
frontend https_front
bind *:443 ssl crt /etc/haproxy/certs/myserver.com.pem
reqadd X-Forwarded-Proto:\ https
acl appA_url url_beg /appA
use_backend appA if appA_url
backend appA
reqrep ^([^\ ]*\ /)appA[/]?(.*) \1\2
redirect scheme https if !{ ssl_fc }
balance roundrobin
server web1 127.0.0.1:5001 check
Use http-request directives, which are processed in declararion order. They are also newer features, and usually cleaner, more intuitive, more flexible, and more internally efficient than reqxxx.
http-request redirect scheme https if ! { ssl_fc }
http-request set-path %[path,regsub(^/appA/,/)]
See http-request. Requires 1.6 or later, where the regsub() converter is available.
I have extremely low knowledge on haproxy. Was testing out a configuration where
S3 hosted website (route 53 alias) - content.mydomain.com
URL landing on haproxy - www.mydomain.com/getfiles/
Is it possible to redirect reroute www.mydomain.com/getfiles/ to content.mydomain.com (s3 hosted website).
I was able to redirect it to another application running on the same server with the below mentioned config
acl display-s3-content path_beg /getfiles/
use_backend my-content if display-s3-content
backend my-content
reqrep ^([^\ ]*)\ (.*) \1\ /path/\2
server test www.mycomain.com:1936
but when i try to redirect it to s3 hosted site, it does not work. Below is the backend for the not working config
reqrep ^([^\ ]*)\ (.*) \1\ /path/\2
server test1 content.mydomain.com
Thanks!
As you noted in comments, this works:
reqirep ^Host: Host:\ content.mydomain.com
The idea is to set the Host header to the value that S3 expects.
A somewhat cleaner approach is this:
http-request set-header Host content.mydomain.com
I say "better" because it uses a newer/better/safer mechanism for header manipulation, but it is fundamentally accomplishing the same purpose: changing the request header to what the destination server (S3) expects. Using the http-request approach is safer/cleaner because it is "smarter" about how it manipulates the request -- it's much easier to completely break the protocol using req[i]rep than it is with http-request.
Originally, you asked about /getfiles/test.jpg mapping to /test.jpg in the bucket. This rewrite is very easy and clean in HAProxy 1.6 and later:
http-request set-path %[path,regsub(^/getfiles,)]
...but in 1.5 you have to use reqirep since the regsub (regex substitution) converter isn't available:
reqirep ^([^\ :]+)\ +/getfiles(.*) \1\ \2
This matches the GET (HEAD, POST, etc.) line from the request and removes the extra /getfiles from the path. Including the : in the exclusion pattern prevents it from matching any other header. A similar pattern can be used to add a prefix (such as a release version, etc.) before sending the request to S3.
I posted a sample config here as well. This config will serve up:
http://<haproxy>/foo/index.html
with index.html sitting on S3.
https://gist.github.com/amslezak/6573767376860ed59a74878fbff6e61f
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).
Apache 2.2.15 on RHELS 6.1
Using mod_pagespeed on a server behind https (implemented by the network's Reverse Proxy).
All html urls are written as "//server.example.com/path/to/file.css" (so, without the protocol specified).
Problem : using the default configuration, pagespeed rewrites the urls as "http://server.example.com/path/to/file.css"
I'm trying to figure out how to have it rewrite the urls as https (or leave it unspecified as //).
After reading the documentation, I tried using ModPagespeedMapOriginDomain like this
ModPagespeedMapOriginDomain http://localhost https://server.example.com
Also tried
ModPagespeedMapOriginDomain http://localhost //server.example.com
ModPagespeedMapOriginDomain localhost server.example.com
... To no avail. Urls keep being rewritten with "http://".
Question: how can I have pagespeed use https instead of http in its urls?
Full pagespeed config here, if needed
It turns out mod_pagespeed does not work with "protocol-relative" urls.
Still, the issue is bypassed if you enable trim_urls
ModPagespeedEnableFilters trim_urls
Be mindful of the potential risks (depending on your javascript codebase, ajax calls could break or produce unexpected html).
Adding this to your configuration might work:
ModPagespeedRespectXForwardedProto on
That works, if your reverse proxy forwards the X-Forwarded-Proto header in its requests.
That request header tells PageSpeed what the original protocol was that was used for the request at the loadbalancer, and thereby hands it all it needs to know to correctly rewrite urls.
I'm a bit out of my depth here and nothing I have found quite addresses my problem. Si any and all suggestions are most welcome.
I've got tomcat6 running on CentOS 6.5 hidden behind an apache server (v2.2.15) and I am using Apache's mod_proxy to expose the tomcat webapps, which are running on port 8080. The tomcat hosts one production application and several development applications. On the apache side, both a Drupal site and the aforementioned tomcat production application are on the same domain and, thanks to rewrite rules, all requests to this domain are changed to https. The development sites are reached via subdomains and do not get re-written as https requests.
For the most part, this arrangement works fine. But parts of the tomcat apps are AJAX (calling a Java Struts 1.2 backend). Most of those requests are handled OK. But a few AJAX requests result in redirects (i.e., forward.setRedirect(true)) and that redirect is http (I guess because the container itself is not secure). As a result, I run into cross site scripting issues. I imagine I can use CORS headers to avoid the problem. But that seems like a hack. Is there a relatively painless way I can use to have tomcat send redirects back as https without making tomcat handle ssl directly?
Cris
You could configure the RemoteIpValve in Tomcat:
Another feature of this valve is to replace the apparent scheme
(http/https) and server port with the scheme presented by a proxy or a
load balancer via a request header (e.g. "X-Forwarded-Proto").
To configure Apache to forward the original protocol in the X-Forwarded-Proto header, add a RequestHeader directive in your Apache config, e.g.:
<VirtualHost *:443>
RequestHeader set X-Forwarded-Proto "https"
...
Note that in Tomcat 7, there is also a RemoteIpFilter.
You don't need to do anything special. It already works. Make sure you set the "redirectPort" in server.xml to Apache's HTTPS port, usually 443, and add the following to your <security-constraint> sections for resources you want secured by HTTPS:
<user-data-constraint>
<description>HTTPS</description>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
Late to the game here but others may find this-- we had a similar setup and issue where everything worked fine until the application started using ajax posts which did redirects for the response. The fix was to use mod_header in apache to rewrite redirects using "Header edit Location"
http://httpd.apache.org/docs/current/mod/mod_headers.html
Header edit Location ^http://www.example.com/ https://www.example.com/
This went unnoticed prior to the ajax redirects because the browser has no problem doing page level redirects to http (which apache would then redirect back to https). But the ajax cross-site prevention halts at the initial http missing out on that would then be redirected to https by a subsequent request.