Plone 3.2.1 and Apache 2.2 on FreeBSD 7.2 behind PF
In 2001, PF was not yet integrated into the OpenBSD kernel. OpenBSD 3.0 soon prevailed (2001) and PF was included in the kernel. Soon thereafter (2003), PF was incorporated into the FreeBSD 5.3 kernel. For those who are unfamiliar, PF is a system for filtering TCP/IP traffic and providing network address translation. However; PF also provides network traffic shaping capabilities - packet prioritization, bandwidth control, and TCP/IP conditioning. My original article from 2000 explained how to setup an IP-less bridge on an OpenBSD 2.8 server running IP Filter with dual network interface cards. The bridge filtered traffic at the data link layer and was invisible at the internet protocol level. PF, like IP Filter, is very powerful. While I will not be going into how to configure an IP-less bridge, the PF configuration that follows is straightforward and easily adaptable.
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
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 the host is rebooted, 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, 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.
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 the host is rebooted, 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: 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
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.