DaemonForums  

Go Back   DaemonForums > Miscellaneous > Guides

Guides All Guides and HOWTO's.

Reply
 
Thread Tools Display Modes
  #1   (View Single Post)  
Old 12th May 2010
Carpetsmoker's Avatar
Carpetsmoker Carpetsmoker is offline
Real Name: Martin
Old man from scene 24
 
Join Date: Apr 2008
Location: Eindhoven, Netherlands
Posts: 2,080
Thanked 198 Times in 156 Posts
Default Run multiple services on one port and use PF's overload to switch between them

Run multiple services on one port and use PF’s overload to switch between them.
Last Updated on 19 May 2010

At work we have a http/https proxy which requires authentication, I would like to access both ssh and a subversion https repository at my server.
The easy solution would be to use two IP addresses. I do not have an additional IP address available.
Using any port other than 443 also has problems, while I do have permission to tunnel these services, past experience have thought that asking the sysadmin to open another port for me would be probably take several months at least.

As a sidenote, you may be wondering why I’m not just using http for my subversion access. The reason is that the HTTP proxy we have doesn’t support certain WebDAV extensions that are required.

The solution
Use pf’s overload feature to switch between services on a given port.

Using it is simple:
I can use svn whenever I need, if I would like to use ssh I open my browser, go to http://94.142.244.51 three times in 42 seconds and I can use ssh.
After closing ssh and waiting for a minute will remove my work’s IP from the rdr_ssh table and I can use svn again.

This solution will work for FreeBSD and OpenBSD. The concept can probably be implemented in most other stateful firewalls too.

/etc/pf.conf
Simplified ruleset for demonstration purposes

Code:
  # Interface to filter
  if="re0"
  
  # My server's IP
  ip="94.142.244.51"
  
  # IP from my work
  work={"80.246.203.133"}
  
  # Table to keep track of who should be redirected from port 443 to port 22
  table <rdr_ssh> persist
  
  # Redirect everyone in the rdr_ssh table from port 443 to port 22
  rdr on $if inet proto tcp from <rdr_ssh> to $ip port https -> $ip port ssh
  
  # Default rules
  block in log
  pass out quick
  
  # Allow traffic on port 443
  pass in on $if proto tcp from any to $ip port https
  
  # Allow traffic on port 80 for svn/ssh "switching", allow it only from my work.
  # Most browsers will try to load /favicon.ico so opening a page once are two
  # connections.
  pass in log quick proto tcp from $work to $ip port http keep state \
    (max-src-conn-rate 6/42, overload <rdr_ssh>)
dummy_server.py
From pf.conf(5)

Code:
       For stateful TCP connections, limits on established connections (connec-
       tions which have completed the TCP 3-way handshake) can also be enforced
       per source IP.
  
       max-src-conn <number>
  	   Limits the maximum number of simultaneous TCP connections which
  	   have completed the 3-way handshake that a single host can make.
  
       max-src-conn-rate <number> / <seconds>
  	   Limit the rate of new connections over a time interval.  The con-
  	   nection rate is an approximation calculated as a moving average.
It took me some time to realize that if no service is running on port 80 the connection attempt will just time out and the 3-way handshake is not completed.

You can use Python to start a simple “donothing webserver”:

Code:
  #!/usr/bin/env python
  
  from BaseHTTPServer import *
  
  host = '94.142.244.51'
  port = 80
  
  HTTPServer((host, port), BaseHTTPRequestHandler).serve_forever()
Or you can use your webserver with a document root of /var/empty/ if you prefer.

/etc/crontab
You can also add a crontab entry to flush the table periodically to switch back to svn when you’re done with ssh.
To your /etc/crontab add:

Code:
  *       *      *       *       *       root /sbin/pfctl -t rdr_ssh -T expire 60 > /dev/null 2>&1
From pfctl(8)(8)

Code:
               -T expire number
                             Delete addresses which had their statistics cleared
                             more than number seconds ago.  For entries which
                             have never had their statistics cleared, number
                             refers to the time they were added to the table.
In other words: As long as a connection is open, the address won’t be removed, but if no connection has been open for 60 seconds the address is removed.

Or, if you prefer, you can manually clear the table with:

Code:
  pfctl -t rdr_ssh -T del <ip>
Further reading
pfctl(8)
pf.conf(5)
PF user’s guide from the OpenBSD site
FreeBSD handbook: 30.4 The OpenBSD Packet Filter (PF) and ALTQ
__________________
UNIX was not designed to stop you from doing stupid things, because that would also stop you from doing clever things.
Reply With Quote
Reply

Tags
pf

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Disabling Services Not Needed EverydayDiesel OpenBSD Security 10 25th January 2010 01:20 PM
Virtual domains on multiple mail servers running Exim4 as MTA satimis General software and network 10 27th November 2008 02:42 PM
start stop services ? smooth187 OpenBSD General 4 31st August 2008 01:00 AM
Questions about my home configuration services aleunix OpenBSD Security 9 12th June 2008 01:54 PM
Learn which services are listening on your box anomie Guides 5 14th May 2008 09:59 AM


All times are GMT. The time now is 02:04 AM.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Content copyright © 2007-2010, the authors
Daemon image copyright ©1988, Marshall Kirk McKusick