I'm running a Tomcat webserver on http port 8080. In front I have an Apache that handles https ssl connections.
How can I know if the client made a request using http:// or https://? Because the following shows http always, because the Apache internally sends only http:8080 requests to the Tomcat of course. So the initial scheme requested is lost here.
HttpServletRequest req;
req.getRequestURL().toString(); // always shows http://....
Apache should add following request headers as explained in mod_proxy docs:
X-Forwarded-For - The IP address of the client.
X-Forwarded-Host - The original host requested by the client in the Host HTTP request header.
X-Forwarded-Server - The hostname of the proxy server.
Additionally X-Forwaded-Proto with the original protocol can be added as explained in this example:
<VirtualHost *:443>
<strong>RequestHeader set X-Forwarded-Proto "https"</strong>
Related
I have an application (JVM 1.8.0_31-b13, Spring MVC 4.2.4, Security 4.0.3) deployed on Tomcat 7 (7.0.68) and I'm using an AWS ELB to handle requests from client.
In my application, I try to get the client ip address using the X-forwarded-for header. If I don't find it, then I use the method getRemoteAddr of the HttpServletRequest class.
And I have noticed several things when I log informations in the application:
First:
The header x-forwarded-for is always null
Second:
The remote address is sometimes the same as the elb ip and sometimes it's the same as client ip address.
I have noticed that:
when the remote address is the same as the client ip address then the request is considered as secured and the scheme is https (method isSecure and getScheme)
when the remote address is the same as the elb address ip then the request is not considered as secured and the scheme is http (method isSecure and getScheme)
Here's the valve configuration in server.xml:
<Valve className="org.apache.catalina.valves.RemoteIpValve" protocolHeader="X-Forwarded-Proto" internalProxies="172\.(1[6-9]|2\d|3[0-1])\.\d{1,3}\.\d{1,3}|10\.\d{1,3}\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3}" />
Here's an example of elb address ip: 172.31.xxx.xxx
I don't understand:
Why the x-forwarded-for header is always null.
And why some requests are considered as secured and some are not.
I have a working tomcat-webapplication at https://very-ugly-and-anoying-domain-name.com:8443/webdir/index.xhtml
Now I want to shorten it to https://appname.nice.com, so it redirects to my internal https://very-ugly-and-anoying-domain-name.com:8443/appname/
For all other applications, I use Nginx to redirect a subdomain http://appname.nice.com to http://very-ugly-and-anoying-domain-name.com:8081/appname/ with
server {
listen 80;
server_name appname.nice.com;
location / {
proxy_pass http://ugly-looooooooooong.domain.com:8081;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
root /data/www/appname;
error_page 403 404 502 503 504 /error.html;
location /error.html {
allow all;
internal;
}
}
But I never had the topic of redirecting a https connection. I think need NOT the stuff of adding the keystore to Nginx because it's already in tomcat.
I do not need HTTP to HTTPS or HTTPS to HTTP. Maybe there is a way to set this directly in Tomcat, but I am not so used to tomcat-config.
How does it work?
Your config doesn't do a "redirect", it simply proxies the request to the host with the "ugly" domain name. For redirect, you would have to return a specific redirect code. For HTTPS, you would need a certificate which has the domain name appname.nice.com in its Subject Alternative Name field because the SSL handshake will look for it. Configure the virtual server with ssl on and use that certificate to terminate SSL. Then you can use a similar config to proxy the HTTPS request to the "ugly" domain name.
I have serverA with haproxy and configuration:
global
log 127.0.0.1 local0
log 127.0.0.1 local1 notice
maxconn 4096
daemon
defaults
log global
mode http
option httplog
option dontlognull
retries 3
option redispatch
maxconn 2000
contimeout 5000
clitimeout 50000
srvtimeout 50000
frontend http-in
bind *:80
default_backend servers
backend servers
option httpchk OPTIONS /
option forwardfor
stats enable
stats refresh 10s
stats hide-version
stats scope .
stats uri /admin?stats
stats realm Haproxy\ Statistics
stats auth admin:pass
cookie JSESSIONID prefix
server tomcat1 serverB:10039 cookie JSESSIONID_SERVER_1
server tomcat2 serverC:10039 cookie JSESSIONID_SERVER_2
Now, i goes to http://serverA/admin?stats and got statistic. On servers serverB and serverC installed WebSphere Application Server and WebSphere Portal Server (WAS it is like Tomcat and WPS it is like any application deployed to Tomcat). It hosts on port 100039. Now i goes to http://serverA/wps/portal and got my portal, but when i click on any link to any page, i got redirect to http://serverA:100039/wps/portal/bla/bla, this happens because WPS response with its port - 100039, but my haproxy configuration listen only 80 port. What i've tried:
option forwardfor
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }
option httpchk HEAD / HTTP/1.1\r\nHost:localhost
For an example, in nginx i got like this:
My application hosts on 3000 port and usefull part of my nginx configuration looks like this:
location #ruby {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_read_timeout 300;
proxy_pass http://app; #upstream app
}
How i can do this in HAProxy?
This question is similar to WebSphere Portal behind reverse proxy and getServerPort()
I think the issue is that WebSphere Application Server (traditional) doesn't honor host headers properly, which can impact getting reverse proxies to work.
Try the settings recommended in that other answer (adjust the apache configuration setting for haproxy), and all should be well.
In your backend section, use "http-request set-header" to set $WSSP and $WSSN to your client-visible hostname and port. They will then be used for self-referential redirects.
Or, set the websphere custom properties trusthostheaderport and com.ibm.ws.webcontainer.extractHostHeaderPort (http://www-01.ibm.com/support/docview.wss?uid=swg21569667) to respect the port in the Host: header.
With this option you may need to ask HAProxy to set the host header to the clients view with "http-request set-header Host" also in the backend section. I'm not sure what the default is.
I'm working with tomcat with a front load balancer. The load balancer take my requests in HTTPS and forward them to tomcat over HTTP. So my tomcat has no SSL configuration and it's working fine so.
My problem is that I've got a response wrapper that does encode redirect some URLs, all my URLs are relative and when I encode redirect my URLs the resulting redirect URL is in HTTP. I'd like it to be HTTPS. I believe this is because tomcat is not in HTTPS, is it possible to enforce HTTPS when doing encode redirect without configuring tomcat with a SSL connector ?
Configure Tomcat to use the RemoteIPValve. This will take the headers that AWS ELB uses to communication the original TLS connection information to the back-end server and wire it into the request object.
This will get you the proper redirect protocol plus you'll also get the original client's IP address when you ask for it, instead of the IP address of the proxy (which is pretty much useless).
Is it possible to get the original request uri after apache proxy the url in java code?
Take a look at the HTTP headers of your request [1] headers like X-Forwarded-For may contain the IP address of the client, X-Forwarded-Host (The original host requested by the client in the Host HTTP request header), X-Forwarded-Server (The hostname of the proxy server). For more detailed explanation see mod_proxy documentation [1].
[1] http://httpd.apache.org/docs/2.2/mod/mod_proxy.html