Redirect HTTP to HTTPS:PORT in Tomcat - apache

I have a running tomcat application that already have the following redirection rule from HTTP to HTTPs:
<Connector executor="tomcatThreadPool"
port="80"
protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="443" />
Is it possible to add an exception/rule, that a specific HTTPrequest (http://www.example.com), will be redirected to another specific address , with a port specified (say https://www.example.com:8443/test), without changing/removing the above Connector ?

You can do it to every app deployed to tomcat by adding this to the end of tomcat_dir/conf/web.xml:
<security-constraint>
<web-resource-collection>
<web-resource-name>Entire Application</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<!-- auth-constraint goes here if you requre authentication -->
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
So you don't have to change it on the web.xml of your webapp.
That should work, assuming you already have https working in another port (usually 443). If you don't, make sure your tomcat_dir/conf/server.xml looks like this:
<!-- Default tomcat connector, changed the redirectPort from 8443 to 443 -->
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="443" />
<!-- To make https work on port 443 -->
<Connector port="443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true">
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol"/>
<SSLHostConfig>
<Certificate certificateKeyFile="/your/own/privkey.pem"
certificateFile="/eyour/own/cert.pem"
certificateChainFile="/your/own/chain.pem"
type="RSA" />
</SSLHostConfig>
</Connector>

The connector configuration you shown does not redirect a specific URL in the way you suppose.
That configuration acts if you have configured a CONFIDENTIAL transport guarantee for a web application inside that servlet container.
I mean, if you have deployed any application on that connector, where its web.xml descriptor has a security-constraint as follows:
<security-constraint>
<web-resource-collection>
<web-resource-name>Secured</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
...
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
Then, Tomcat will redirect any matching url-pattern to the configured port in order to use HTTPS as guarantor of confidentiality in transport.
So, if you want to redirect a specific URL, you have to complement connector's configuration with specific application configuration.
Edit
As you suggest in your comment, it could be another step to get this configuration working. Once you have configured http connector as shown, and then configured app as I told you, you only to ensure that your Tomcat server has an HTTPS connector configured, other way redirection won't work.
To configure this HTTPS connector, you can use a configuration as following:
<Connector connectionTimeout="20000"
acceptCount="100" scheme="https" secure="true"
port="443" clientAuth="false" sslProtocol="TLS"
keystoreFile="PATH_TO_KEY_STORE"
keystorePass="KEY_STORE_PASS"
keyAlias="KEY_STORE_ALIAS"/>
This is a sample configuration where I didn't put some attributes that can be important for you as threads attrs, executors, and so on.
The most important thing is the KeyStore configuration that you need to serve HTTPS connections. Here you have the official documentation to prepare a java KeyStore for Tomcat to serve HTTPS.

I have a running tomcat application that already have the following redirection rule from HTTP to HTTPs:
As malaguna answered, that Connector configuration is not a redirection rule. It is just a setting that is used when performing redirection triggered by <transport-guarantee>CONFIDENTIAL</transport-guarantee>.
There is no way to overwrite that setting on per-application basis.
If you need better control over such redirection, you need to implement your own Filter that will implement a redirection (if (!request.isSecure()) { response.sendRedirect(...);}), or configure a 3rd party one.
// Technically, in current Tomcat 8 code the redirection triggered by transport-guarantee is performed by org.apache.catalina.realm.RealmBase.hasUserDataPermission(...) method.

If you use tomcat with httpd, you can use RewriteEngine.
With port specified is like the followings in the http.conf:
NameVirtualHost *:8443 #your specified port
<VirtualHost *:8443>
ServerName www.example.com
Redirect permanent / https://secure.example.com/
</VirtualHost>
See: RewriteHTTPToHTTPS and Redirect Request to SSL

Putting transport-guarantee CONFIDENTIAL in conf/web.xml is good, but it does not cover the manager app and the host-manager app (Tomcat 8.5.38).
My solution is to put a valve in conf/context.xml that redirects all http requests to https.
https://bitbucket.org/bunkenburg/https-valve/src/master/

It's too late to answer, still I'm sharing my experience over the same, do the following changes in
Apache Software Foundation\Tomcat 8.5\conf\web.xml
Take a restart.
Pre-Req: configure https port and disable http port(optional[I did it])

<Connector connectionTimeout="20000" port="8081" protocol="HTTP/1.1" redirectPort="443"/>
<Connector port="443"
SSLEnabled="true"
acceptCount="100"
disableUploadTimeout="true"
enableLookups="false"
maxHttpHeaderSize="8192"
maxThreads="550"
minSpareThreads="25"
scheme="https"
secure="true"
compression="on"
protocol="org.apache.coyote.http11.Http11NioProtocol"
sslImplementationName="org.apache.tomcat.util.net.openssl.OpenSSLImplementation">
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol"/>
<SSLHostConfig protocols="TLSv1.2"
certificateVerification="none"
ciphers="TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA">
<Certificate type="RSA"
certificateKeystoreFile="/ssl/self-signed/your-keystore.jks"
certificateKeystorePassword="123456"
certificateKeyAlias="your-alias" />
</SSLHostConfig>
   </Connector>

Related

Tomcat 9 - long https request

I am sending a request that includes media and has a contentLength of about 200k.
It works fine when sending to the non-SSL port but when sending to the SSL port
the ByteBuffer of the request's Reader does not contain all the request.
I think it has to do with the appReadBufSize setting.
A shorter, 255-byte SSL request works fine - so the problem is not with SSL
but has to do with the length.
I suppose it should be possible to pass long SSL requests to Tomcat but did not
find any reference about the difference between SSL and non-SSL handling of long requests. The connector uses openssl.
server.xml connector definitions:
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
connectionTimeout="20000" maxPostSize="-1"
maxThreads="150" SSLEnabled="true" sslProtocol="TLS"
scheme="https" secure="true" clientAuth="false"
... SSL keystore definitions/>
Please advise,
Many thanks,
Yuval
It turned out that there was indeed a bug in Tomcat:
http://tomcat.10.x6.nabble.com/Bug-64486-New-Receiving-null-empty-request-body-when-SSL-enabled-td5099846.html
I was running Tomcat 9.0.31 under Ubunto 20. The problem disappeared when upgrading to Tomcat 9.0.37 (manual install).

Redirect http to https on Tomcat 7 application

I have a webapp application running on Tomcat7 which connects easily via https but returns Unable to connect error when accessed without it.
Below is my server.xml file content
<Service name="Catalina">
<Connector protocol="org.apache.coyote.http11.Http11Protocol"
port="443"
maxThreads="200" scheme="https"
secure="true" SSLEnabled="true"
keystoreFile="/usr/share/.keystore"
Host is Amazon lightsail and port 80 and 443 are available. I noticed port 80 which is meant to enable non-http traffic is not in use. 443 is anyway.
I have tried other methods on SO and other blogs, none seem to be working.
Finally,
I stumbled on what could have been the troubling issue.
After adding the connector code for port 80 and redirecting to 443.
I changed this section of my code to
<Service name="Catalina">
**<Connector port="443" protocol="HTTP/1.1"**
maxThreads="200" scheme="https"
secure="true" SSLEnabled="true"
keystoreFile="/usr/share/.keystore"
keystorePass="xxx111!!"
And editing the web.xml file as always advised. I guessed the major change was in the code section below.
Hoping this helps someone out there.

Mix https and http on single tomcat instance

I have an application which in general works in https. Tomcat listens on port 8443:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keyAlias="MY_ALLIAS" keystoreFile="PATH_TO_MY_KEY"
keystorePass="MY_PASWORD" />
Apache listens on 80 and redirects to 8443:
<VirtualHost *:80>
ServerAdmin MY_EMAIL_ADDRESS
ServerName localhost
ServerAlias localhost
ProxyPass / http://localhost:8443/
ProxyPassReverse / http://localhost:8443/
DocumentRoot /var/www/html
Finally in web.xml there I added:
<security-constraint>
<web-resource-collection>
<web-resource-name>MY_WEB_RESOURCE_NAME</web-resource-name>
<url-pattern>/welcome</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
Unfortunatly I have to add IFRAME with http site into one of my websites. Security is not a problem there. My problem is Tomcat configuration. I guess I will dispatch traffic with Apache. But now my question is how to setup Tomcat, so I can serve site http://localhost:8080/siteA and all the other sites will be served on https://localhost:8443/myOtherSites? I tried removing redirectPort="8443", but it's not enough. I'm using Tomcat 9.0.0.M4 (it's not a problem to move to Tomcat 8, if I would need to).
Please help!
To Solve this problem add one more <security-constraint> tag in your web.xml like this `
<security-constraint>
<web-resource-collection>
<web-resource-name>Unsecured resources</web-resource-name>
<url-pattern>/siteA</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint> `
Since you have set transport-guarantee as NONE , tomcat will not verify if its a secured resource or not . In this manner this <security-constraint> will help to access your siteA over http and the other<security-constraint> tag that you have already declared will help you access your other sites on https. Just remember in <url-pattern> tag give path to the pages that you want to keep as http or https Let me know if this solves your problem :) .

AWS load balancer always routes 443 to 8443

I am serving up content on an ec2 instance running tomcat 7. I have all traffic routing in the tomcat config to 8443 and a valid cert installed. When i explicitly put https://website.com:443 the site loads fine, but when i put in http://website.com it should route to the https with port 443, but it uses the port 8443 instead. Anyone have any idea why this would be happening? I have the exact same config working on another server but i have two new servers that dont want to behave.
in my tomcat server.xml i have:
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
sslEnabledProtocols="TLSv1,TLSv1.1,TLSv1.2"
ciphers="TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_RC4_128_SHA,
TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA256,
TLS_RSA_WITH_AES_256_CBC_SHA,SSL_RSA_WITH_RC4_128_SHA"
keystoreFile="conf/cert.p12"
keystorePass="password"
keystoreType="PKCS12" />
and in web.xml:
<security-constraint>
<web-resource-collection>
<web-resource-name>Protected Context</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<!-- auth-constraint goes here if you requre authentication -->
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
Found an answer to this, turns out i had to route all traffic over TCP from 8443 to 8443. The client was requesting port 80, routing to 8080 per my load balancer config for tomcat to serve up content, tomcat was turning the request into requesting port 8443.
8443 wasnt being routed back to 8443 on the tomcat server so it just ended up in a dead end. hope this helps someone else someday.
Tomcat sends a redirect when using a transport-guarantee of CONFIDENTIAL
By default this is your connector port. Run a curl -vs http://website.com to confirm.
You could set the http/8080 connectors redirectPort to 443 but this means you are choosing ELB redirects to work. Local Tomcat redirects will then start failing as nothing listens locally on 443, just the ELB does.

Tomcat SSL Configuration

I received a SSL cert to use for a Tomcat 6.0 server, ready to use.
I configured Tomcat to use it with the following in server.xml:
<Connector
port="8443" maxThreads="200"
scheme="https" secure="true" SSLEnabled="true"
keystoreFile="C:\Tomcat 6.0\ssl\cert" keystorePass="*****"
clientAuth="false" sslProtocol="TLS"/>
I started Tomcat using the command prompt so I could see any error message as they happened. There were none.
The results for accessing different URLS:
http://localhost -> normal page loads fine
https://localhost -> browser claims page cannot be found
https://localhost:8443 -> page cannot be found
http://localhost:8443 -> offers a certificate, after accepted redirects to https://localhost (I suspect the https:// urls initially offer the certificate which is automatically accepted by the browser, as it was issued by Verisign)
How to fix?
Edit: I've also tried port="443". Same result.
Do you require SSL on both 8443 and 443?
If all you need is 443 (the standard HTTP port), you can simply change the port="8443" to "443" and https:// URLs should work fine.
EDIT:
OK, so if you've made the change and bounced tomcat and it's still listening on 8443 then there must be another connector specified which is listening on 8443.
Here's my connector configuration from my server.xml
<Connector
port="8080"
redirectPort="443"
maxSpareThreads="75"
maxThreads="150"
minSpareThreads="25"
compression="on"
compressionMinSize="2048"
noCompressionUserAgents="gozilla, traviata"
compressableMimeType="text/html,text/xml,text/javascript,application/xml">
</Connector>
<Connector
port="443"
minProcessors="5"
maxProcessors="75"
keystorePass="*****"
enableLookups="true"
disableUploadTimeout="true"
acceptCount="100"
debug="0"
scheme="https"
secure="true"
clientAuth="false"
sslProtocol="TLS"
compression="on"
compressionMinSize="2048"
noCompressionUserAgents="gozilla, traviata"
compressableMimeType="text/html,text/xml,text/javascript,application/xml">
</Connector>
That results in traffic coming in on 8080 being (internally) redirected to the connector on port 443. Traffic from 443 doesn't have any redirect directive.
I'd do a grep of your configurations for 8443 to make sure another one hasn't sneaked in somewhere.
I looks like you referenced a cert file in the keystoreFile attribute... if that file is actually a cert file you should use something like this
SSLCertificateFile="C:\Tomcat 6.0\ssl\cert"
... if that is correct (that the file a cert) then you will also need a key, for example:
SSLCertificateKeyFile="C:\Tomcat 6.0\ssl\cert.key"
If you have intermediate certs that you need in the CA chain, add:
SSLCertificateChainFile=