Search code examples
linuxamazon-ec2dnsjettyjetty-9

Using non default HTTPS port without writing it in URL on Jetty/Linux


Jetty 9.3.8.v20160314 running on AWS EC2 Linux machine with Java 1.8.0_51 has two virtual hosts defined under two different contexts - webapps/app1 and webapps/app2 with an empty webapps/ROOT directory.

Each web context has its own SSL connector with proper keystore assigned, of two different domain names, let's say www.example1.com and www.example2.com.

The problem is that each SSL connector has to use a different port, so first app would have port 443 but the second use 444, which is not the default port for HTTPS calls. Now, app2's clients would have to use https://www.example2.com:444 which is not pretty.

Is there some workaround to omit the :444 part?

Maybe it is possible to define a something on WebAppContext.xml to forward calls to port 444, or maybe in the DNS zone file?

Perhaps this can be done on the Linux level, using iptables?

Content of webapps/appX.xml -

<?xml version="1.0"  encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">

<Configure class="org.eclipse.jetty.webapp.WebAppContext">
  <Set name="contextPath">/</Set>
  <Set name="war">
    <SystemProperty name="jetty.home" default="."/>/webapps/appX
  </Set>
  <Set name="virtualHosts">
     <Array type="java.lang.String">
       <Item>www.exampleX.com</Item>
     </Array>
  </Set>

  <!-- by Code Range -->
  <Get name="errorHandler">
    <Call name="addErrorPage">
      <Arg type="int">400</Arg>
      <Arg type="int">599</Arg>
      <Arg type="String">/</Arg>
    </Call>
  </Get>
</Configure>

Contents of etc/jetty-ssl.xml -

<Configure id="Server" class="org.eclipse.jetty.server.Server">
    ... 
  <Call  name="addConnector">
    <Arg>
      <New id="sslConnector2" class="org.eclipse.jetty.server.ServerConnector">
        <Arg name="server"><Ref refid="Server" /></Arg>
        <Arg name="acceptors" type="int"><Property name="jetty.ssl.acceptors" deprecated="ssl.acceptors" default="-1"/></Arg>
        <Arg name="selectors" type="int"><Property name="jetty.ssl.selectors" deprecated="ssl.selectors" default="-1"/></Arg>
        <Arg name="factories">
          <Array type="org.eclipse.jetty.server.ConnectionFactory">
          </Array>
        </Arg>

        <Set name="host"><Property name="jetty.ssl.host" deprecated="jetty.host" /></Set>
        <Set name="port">8444</Set>
        <Set name="idleTimeout"><Property name="jetty.ssl.idleTimeout" deprecated="ssl.timeout" default="30000"/></Set>
        <Set name="soLingerTime"><Property name="jetty.ssl.soLingerTime" deprecated="ssl.soLingerTime" default="-1"/></Set>
        <Set name="acceptorPriorityDelta"><Property name="jetty.ssl.acceptorPriorityDelta" deprecated="ssl.acceptorPriorityDelta" default="0"/></Set>
        <Set name="acceptQueueSize"><Property name="jetty.ssl.acceptQueueSize" deprecated="ssl.acceptQueueSize" default="0"/></Set>
      </New>
    </Arg>
  </Call>
   ...
</Configure>

SSL connector is set to port 8444 and forwarded by iptables from external port 444 -

sudo iptables -t nat -I PREROUTING -p tcp --dport 444 -j REDIRECT --to-port 8444

Solution

  • There is no workaround to omit the port. If you specify an HTTPS URL without a port, you are in fact implicitly specifying port 443.

    I would suggest looking into placing an Nginx reverse proxy in front of your Jetty applications, and have it forward requests to the appropriate port based on the domain name being requested.