A major step towards enhancing application security is to safeguard web interfaces of an application by enforcing SSL with proper TLS version and restrict access over non-secure communication over http.
In this blog, I will explain proxy and application servers coupling, as well as enablement of ssl at the proxy.
Consider a scenario where you have a set of applications hosted in tomcat or jboss servers, few of the application has single instance and others has multiple instances with session handing to ensure HA.
Please follow the below steps to achieve goal of enhancing application security is to safeguard web interfaces of an application by enforcing SSL with proper TLS version and restrict access over non-secure communication over http.
Application Server
We will use ajp protocol for communication between proxy and the application servers. The ajp13 protocol is packet-oriented, high performing protocol.
Please follow the below link to know more about AJP protocol-
https://tomcat.apache.org/connectors-doc/ajp/ajpv13a.html
Add below in tomcat server.xml to enable AJP(default port 8009)
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
Add below in Jboss or to enable AJP(default port 8009),
# under web subsystem
<connector name="ajp" protocol="AJP/1.3" socket-binding="ajp"/>
#socket-binding-group
<socket-binding name="ajp" port="8009"/>
Also add jvmRoute in application servers.
Proxy
Set up a HA proxy using keepalived with VIP at least on two servers irrespective of type of proxy.
Copy certificates received from CA into both the proxy servers.
I am going to discuss configuration of most widely used proxy Apache with mod proxy, HAPROXY and nginx. You could consider having any one of them.
Apache with mod proxy
Following modules to be enabled.
Please have a module configuration as below
LoadModule proxy_module modules/mod_proxy.so
LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule proxy_http_module modules/mod_proxy_http.so
Frontend or interface exposed for external traffic are protected with SSL.
Please place a ssl.conf inside conf.d folder.
#Enable port listener
listen 443 https
#Global SSL config
SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog
SSLSessionCache shmcb:/run/httpd/sslcache(512000)
SSLSessionCacheTimeout 300
SSLRandomSeed startup file:/dev/urandom 256
SSLRandomSeed connect builtin
SSLCryptoDevice builtin
#SSL Virtual Host Context
<VirtualHost *:443>
#DocumentRoot "/var/www/html"
ProxyPreserveHost On
ServerName <<FQDN or domain name>>
LogLevel info
TransferLog /var/log/httpd/ssl_access_log
ErrorLog /var/log/httpd/ajp.error.log
CustomLog /var/log/httpd/ajp.log combined
SSLEngine on
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite HIGH:3DES:!aNULL:!MD5:!SEED:!IDEA
#certificates
SSLCertificateFile /etc/pki/tls/certs/domain.crt
SSLCertificateKeyFile /etc/pki/tls/private/domain.key
SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt
#SSLCACertificateFile /etc/pki/tls/certs/ca-bundle.crt
#SSLVerifyClient require
#SSLVerifyDepth 10
<Proxy *>
AddDefaultCharset Off
Order deny,allow
Allow from all
</Proxy>
</VirtualHost>
Proxy & reverse proxy configuration for backend without load balancer
Below entry added under ssl virtual host tag of ssl.conf
ProxyPass /ApplicationContext ajp://[Application Server IP]:[port]/ApplicationContext
ProxyPassReverse /ApplicationContext ajp://[Application Server IP]:[port]/ApplicationContext
Below entry added under ssl virtual host tag of ssl.conf
<Proxy balancer://lb_name>
BalancerMember ajp://[ApplicationServer#1 ip]:[port]/[ApplicationContext] route=[ApplicationServerName or ID]
BalancerMember ajp://[ApplicationServer#2 ip]:[port]/[ApplicationContext] route=[ApplicationServerName or ID]
ProxySet lbmethod=bytraffic
ProxySet stickysession=JSESSIONID
</Proxy>
ProxyPass /ApplicationContext balancer://lb_name stickysession=JSESSIONID
ProxyPassReverse /ApplicationContext balancer://lb_name stickysession=JSESSIONID
Apache httpd proxy uses mod_proxy and ajp module to redirect to backends.
Below conf to be added to httpd.conf
#redirect all http request to https
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
Restart the apache2/httpd service
HAPROXY
Following details to be added to haproxy.conf
HAPROXY Global Configuration
global
log /opt/log local0
daemon
maxconn 50000
ssl-default-bind-options no-sslv3
tune.ssl.default-dh-param 2048
stats socket /var/lib/haproxy/haproxy.sock mode 0600 level admin
defaults
log global
mode tcp
option tcplog
option dontlognull
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
# errorfile 503 /etc/haproxy/errors/503.http
# errorfile 504 /etc/haproxy/errors/504.http
Define a SSL enable frontend with 80 to 443 redirection
#------------SSL enabled frontend------------------------------
frontend https-app-fnd
bind *:443 ssl crt /etc/pki/tls/certs/domain.pem force-tlsv12
bind *:80
mode http
reqadd X-Forwarded-Proto:\ https
#http to https force redirect
http-request redirect scheme https unless { ssl_fc }
use_backend proxy-app-bnd
Define a backend for the above frontend
#------------non SSL enabled backend------------------------------
backend proxy-app-bnd
mode http
balance roundrobin
option httpchk OPTIONS /
option forwardfor
option http-server-close
cookie SERVERID insert indirect nocache
# cookie JSESSIONID prefix nocache
server appserver1 [appserver1 ip]:[port] check cookie appserver1
server appserver2 [appserver2 ip]:[port] check cookie appserver2
server appserver3 [appserver3 ip]:[port] check cookie appserver3
Restart the haproxy service and test.
NGINX
Following details to be added in nginx.conf if you are using nginx.
Global ssl config
# --------- global ssl config -------------------
ssl_certificate /etc/pki/tls/certs/domain.crt;
ssl_certificate_key /etc/pki/tls/certs/domain.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_verify_depth 3;
Add the below section only if you have backend applications deployed on multiple servers(HA config)
# below http section is for applications with multiple backend only
http {
upstream app_with_multiple_backend {
server [appserver1 ip]:[port];
server [appserver2 ip]:[port];
server [appserver3 ip]:[port];
sticky cookie srv_id expires=1h domain=.[yourdomain] path=/;
}
Then add the below section under server tag only if you have backend applications deployed on multiple servers(HA config).
# applications with multiple backend, definition of app_with_multiple_backend is at outside server tag
location / {
proxy_pass http://app_with_multiple_backend;
}
Add the below if you have single application instance deployed.
# applications with single backend
location /applicationContext1 {
proxy_pass http://[application server ip]:[port]/[applicationContext1]
}
Restart the nginx service and test.
Please clone below git repo for more.
Git repo: https://github.com/tech-inducers/securing_applications_ssl_proxy