You are here: Home Docs Miscellaneous Plone behind Apache 2 on FreeBSD 7 with PF

Plone behind Apache 2 on FreeBSD 7 with PF

by Bryan Hinton last modified May 05, 2010 11:06 PM
— filed under: , ,

Plone behind Apache and Varnish on FreeBSD 7 with PF (UPDATE May 04, 2010)

 

 

UPDATE (MAY 04, 2010)

- An updated version of this configuration with Plone 3.3.5 and Squid can be found on plone.org at the following page:
Plone 3 - Apache2/SSL - Squid on FreeBSD 7 with PF

 

This document shows an example configuration of a PF ruleset and an Apache 2.2 installation in front of a Plone 3.2.1 instance on FreeBSD 7.2.  SSH tunnelling is used for remote management of the Zope/Plone instance (i.e. ZMI).

 

Pre-installation Requirements

  • FreeBSD 7.2-PRERELEASE w/ PF enabled
  • Apache 2.2 from (from ports) with mod_ssl (OpenSSL 0.9.8j), mod_proxy, and mod_rewrite
  • Zope w/ Plone 3.2.1
  • Varnish HTTP Accelerator

 

Zope is bound to an unprivileged port on localhost.  Apache is bound as a non-privileged user to port 80 and 443 on public IP address X.X.X.Y.  Zope/Plone can be running standalone or in a ZEO Server / ZEO client configuration.  In either case, Apache will function as a reverse proxy and send http requests to Zope.

 

Enable IP Forwarding in the Kernel

If you have not already done so, enable IP forwarding in the kernel:

# sysctl net.inet.ip.forwarding=1
# sysctl net.inet.ip.fastforwarding=1
# sysctl net.inet6.ip6.forwarding=1

Add the following lines to /etc/sysctl.conf so that when you reboot, IP forwarding is enabled:

# /etc/sysctl.conf

net.inet.ip.forwarding=1
net.inet.ip.fastforwarding=1
net.inet6.ip6.forwarding=1
kern.ipc.somaxconn=4096
kern.ipc.nmbclusters=32768

As an alternative, you can add the following to /etc/rc.conf

# /etc/rc.conf

gateway_enable="YES"

 

Enable HTTP Accept Filter

Next, make sure that the HTTP Accept filter is loaded into the kernel.

You can check this by running the following command:

# kldstat

2    1 0xc0b12000 2464     accf_http.ko

If the filter is not loaded, edit /boot/loader.conf and add the following line so that when you reboot, the HTTP Accept filter kernel module is loaded.

# /boot/loader.conf
 accf_http_load="YES"

Last of all, to load the module without rebooting, run the following command:

kldload accf_http

 

System V Shared Memory and Semaphore Parameters

Modify System V shared memory and semaphore parameters

# sysctl kern.ipc.shmall=32768
# sysctl kern.ipc.shmmax=134217728
# sysctl kern.ipc.semmap=256

Make these changes permanent by adding the following to /etc/sysctl.conf

# /etc/sysctl.conf

kern.ipc.shmall=32768
kern.ipc.shmmax=134217728
kern.ipc.semmap=256
net.inet.ip.forwarding=1
net.inet.ip.fastforwarding=1
net.inet6.ip6.forwarding=0
kern.ipc.somaxconn=4096
kern.ipc.nmbclusters=32768

 

System V "Read-Only" Semaphore Parameters

Modify the System V "Read-Only" Semaphore Parameters by adding the following to /boot/loader.conf  

NOTE: You must reboot for the new values of these parameters to take effect

# /boot/loader.conf

kern.ipc.semmni=256
kern.ipc.semmns=512
kern.ipc.semmnu=256
accf_http_load="YES"
net.inet.tcp.syncache.hashsize=1024
net.inet.tcp.syncache.bucketlimit=100
net.inet.tcp.tcbhashsize=4096
net.inet.tcp.syncache.cachelimit=102400

 

PF Configuration

# /etc/pf.conf
#

## MACROS-----
ext_if="bge0"
set loginterface $ext_if
local_networks = "{ a.a.a.b/24, c.c.c.d/24, e.e.e.f/26}"
internet_ports = "{80, 443}"

# Table Setup
# /etc/iface_addresses contains the following
# X.X.X.Y
# X.X.X.Z
table <iface_addresses> persist file "/etc/iface_addresses"
table <bruteforce> persist

# set Block Policy option
set block-policy return

# set Skip Filtering option on localhost
set skip on lo0

scrub in all
antispoof quick for $ext_if inet

# block ip addresses contained in bruteforce table
block in log (all, to pflog0) quick on $ext_if from <bruteforce> to any

# block and then log outgoing packets that don't have one of our IPs as the source IP
block out log (all, to pflog0) quick on $ext_if from ! <iface_addresses> to any

# block nmap scans
block in log (all, to pflog0) quick on $ext_if inet proto { tcp, udp } from any to any flags FUP/FUP

# block everything by default
block in on $ext_if all

# pass in icmp and keep state
pass in quick on $ext_if inet proto icmp all keep state

# pass in tcp traffic from localhost
pass in quick on $ext_if proto tcp from 127.0.0.1 to <iface_addresses>

# pass in traffic on internet ports
pass in on $ext_if proto { tcp, udp } from any to <iface_addresses> port $internet_ports flags S/SA keep state

# throttle ssh connection attempts and block their ip if a bruteforce attempt is detected
pass in quick on $ext_if proto tcp from any to any port ssh \
     flags S/SA keep state \
     (max-src-conn 15, max-src-conn-rate 5/3, \
      overload <bruteforce> flush global)

# allow traffic from interface addresses to localhost
pass out quick on $ext_if from <interfaces_addresses> to 127.0.0.1

# allow local network admin ip addresses
pass in on $ext_if proto { tcp, udp } from $local_networks to $ext_if

# keep state on outbound connections made from one of the ip addresses on interface
pass out on $ext_if proto tcp from any to any flags S/SA modulate state
pass out on $ext_if proto { udp, icmp } from any to any keep state


 Apache Configuration

# /usr/local/etc/apache22/httpd.conf
# ---------------------------------- 


Listen X.X.X.Y:80 # Default
Listen X.X.X.Z:80 # VHost
Listen X.X.X.Z:80:443 # VHost

HTTP Virtual Hosts

# /usr/local/etc/apache22/Includes/httpd-vhosts.conf
# --------------------------------------------------
NameVirtualHost X.X.X.Z:80

<VirtualHost X.X.X.Z:80>
   ServerName DOMAIN.com
   ServerAlias www.DOMAIN.com
   ServerAdmin info@DOMAIN.com
   ServerSignature On
   RequestHeader set Front-End-Https "On"
   ProxyRequests Off
   ProxyPreserveHost On

   ErrorLog "/var/log/DOMAIN-error_log"
   CustomLog "/var/log/DOMAIN-access_log" common
   LogLevel warn

   <IfModule mod_rewrite.c>
      RewriteEngine On
      RewriteLogLevel 2
      RewriteRule ^/icons/ - [L]
      RewriteRule ^/(.*)/manage(.*) \
      https://DOMAIN.com/$1/manage$2 [NC,R=301,L]
      RewriteRule ^/manage(.*) \
      https://DOMAIN.com/manage$1 [NC,R=301,L]
      RewriteRule ^/login_(.*) https://%{SERVER_NAME}/login_$1 [NE,L]
      RewriteRule ^/(.*) \
         http://127.0.0.1:8902/VirtualHostBase/http/%{SERVER_NAME}:80/MyPloneSite/VirtualHostRoot/$1 [P,L]
    </IfModule>
    <IfModule mod_proxy.c>
       ProxyVia On
       ProxyPass / http://127.0.0.1:8902/VirtualHostBase/http/%{SERVER_NAME}:80/MyPloneSite/VirtualHostRoot/
       ProxyPassReverse / http://127.0.0.1:8902/VirtualHostBase/http/%{SERVER_NAME}:80/MyPloneSite/VirtualHostRoot/
       <ProxyMatch http://127.0.0.1:*/.* >
          Order deny,allow
          Deny from all
          Allow from X.X.X.Y
       </ProxyMatch>
       <LocationMatch "^[^/]">
          Deny from all
       </LocationMatch>
    </IfModule>
</VirtualHost>

SSL Virtual Hosts

# /usr/local/etc/apache22/Includes/httpd-ssl.conf

NameVirtualHost X.X.X.Z:443

<VirtualHost X.X.X.Z:443>
   DocumentRoot "/usr/local/www/apache22/data"
   ServerName DOMAIN.com
   ServerAdmin info@DOMAIN.com
   ErrorLog "/var/log/DOMAIN-ssl-error.log"
   TransferLog "/var/log/DOMAIN-ssl-access.log"

   SSLEngine on
   SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+SSLv3:+EXP:+eNULL
   SSLCertificateFile "/usr/local/etc/apache22/ssl.crt/DOMAIN.com.crt"
   SSLCertificateKeyFile "/usr/local/etc/apache22/ssl.key/DOMAIN.com.key"

   <FilesMatch "\.(cgi|shtml|phtml|php)$">
      SSLOptions +StdEnvVars
   </FilesMatch>
   <Directory "/usr/local/www/apache22/cgi-bin">
      SSLOptions +StdEnvVars
   </Directory>
   BrowserMatch ".*MSIE.*" \
   nokeepalive ssl-unclean-shutdown \
   downgrade-1.0 force-response-1.0

   CustomLog "/var/log/cfhinton-ssl_request.log" \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

    <IfModule mod_rewrite.c>
      RewriteEngine On
      RewriteLogLevel 2

      RewriteRule ^/(.*) \
         http://127.0.0.1:8902/VirtualHostBase/https/%{SERVER_NAME}:443/MyPloneSite/VirtualHostRoot/$1 [L,P]
    </IfModule>
    <IfModule mod_proxy.c>
       ProxyVia On
       ProxyPass / http://127.0.0.1:8902/VirtualHostBase/http/%{SERVER_NAME}:80/MyPloneSite/VirtualHostRoot/
       ProxyPassReverse / http://127.0.0.1:8902/VirtualHostBase/http/%{SERVER_NAME}:80/MyPloneSite/VirtualHostRoot/
       <ProxyMatch http://127.0.0.1:*/.* >
          Order deny,allow
          Deny from all
          Allow from X.X.X.Y
       </ProxyMatch>
       <LocationMatch "^[^/]">
          Deny from all
       </LocationMatch>
    </IfModule>
</VirtualHost>

SSH Tunnel (access ZMI via http://localhost:9999

ssh -f user@mydomain.com -L 9999:localhost:8095 -N

 

Document Actions