Posted by Tres
Mon, 15 Oct 2007 05:10:00 GMT
An easy way to get OpenBSD to allow remote binary installs via pkgadd is to set up your .profile or .bashprofile with the following:
export PKG_PATH=http://mirror.planetunix.net/pub/OpenBSD/`uname -r`/packages/`uname -m`/
Once you’ve got that, you can automatically add packages.
You might want to find a closer mirror depending on where you are: from here: http://www.openbsd.org/ftp.html
Posted in OpenBSD, Sysadmin
Posted by Tres
Tue, 26 Dec 2006 02:51:00 GMT
Another one of the brilliant ideas to come out of OpenBSD is the interface group.
OpenBSD’s interface groups combined with VLAN interfaces are the one of the best tools available to simplify the management and organization of your rulesets. By using interface groups, you can cut out 99% of the redundancy required for different networks. The best part of interface groups from a management perspective is that they allow you to see instantly what rules are being used on any given interface. It’s like a heads-up display of what rules are applied to any subnet on the network.
Using interface groups is very easy. You can add an interface to a group by using the “group” option of ifconfig. So to add interface vlan1024 to the DEVELOPER interface group, I would do this:
ifconfig vlan1024 group DEVELOPER
If I wanted to remove interface vlan1024 from the DEVELOPER interface group, I would do this:
ifconfig vlan1024 -group DEVELOPER
To add a group to a particular interface on boot just add the “group” syntax to the hostname.if file for the vlan group. So to add DEVELOPER rules to the vlan1024 interface at boot, your /etc/hostname.vlan1024 file would add an additional line to the end of the file like this:
10.18.24.254 netmask 255.255.0.0 broadcast 10.18.24.255 vlan 1024 vlandev em2
group DEVELOPER
You can add as many groups to an interface as are necessary, just keep adding each group to the interface on a separate line and use the “group” syntax:
10.18.24.254 netmask 255.255.0.0 broadcast 10.18.24.255 vlan 1024 vlandev em2
group DEVELOPER
group IMAP
group SMTP
group POP3
group HTTP
group INTERNET
There’s no extra configuration required to get PF to use the group. All you need is to set up your rules for the interface group. Rules should have as fine of granularity as possible. Remember, you’re trying to show exactly what rules are being used by the interfaces. You should use use super-classes to define more abstract groupings sparingly. It can lead to confusion if a rule for a service is defined in a superclass because it is in use by all hosts on the network. It is better to use service based group interface rules that are applied to all interfaces. Then there is no confusion. So, what does our service-based group interface ruleset look like?
pass in quick proto tcp on INTERNET from <our_ips> to !<our_ips> keep state flags S/SA
pass out quick proto tcp on INTERNET from <our_ips> to !<our_ips> modulate state flags S/SA
That’s it. Of course these rules imply that you’re using tables to manage addresses.
So, you can add a base set of rules to any interface that you’ve defined. If you have your VLANs and switchports set up so things are managed by access levels, interface groups make things brilliantly easy. Just plug in the rules that apply to that group and you’re done. If you have mixed networks in which only a few workstations get access, don’t despair. Using address tables in conjunction with the group will allow use of interface groups. Just define the IP addresses in the relevant table, and as long as you’ve written your rules to only use the table you’re ready.
Posted in OpenBSD, PF / CARP , Sysadmin | Tags firewall, groups, interface, management
Posted by Tres
Mon, 25 Dec 2006 00:08:00 GMT
Splitting rules into multiple files allows you to easily organize rules, but the downside is that without a little scripting, you can’t really use macros effectively. Because of the way anchors work, you have to define macros in each file separately. This is a potential management overhead nightmare.
The #<–[MACROS]–> construct allows us to define all macros in a single file and distribute it to all anchor files. We keep all our macros in /usr/local/etc/pf_macros.conf. Just by putting #<–[MACROS]–> at the start of our ruleset, we can ensure that our single set of macros will be used in that file. That way, we can keep management overhead to a minimum. Here’s the ruby script that makes that possible:
#!/usr/bin/env ruby -w
# macros.rb
# script which will push macro variables from one file into all anchors files and pf.conf
# this should be run with cfengine, so when files get pushed out, or changed, the
# macros will automatically be defined.
# to allow this file to automatically push uniform macros to your pf anchors and pf.conf
# place a line like the following into the file you want to have macros pushed into
#<--[MACROS]-->
# this script will replace the entire line within which the <--[MACROS]--> element is used
require 'find'
require 'fileutils'
require 'date'
pf_base_conf_dir="/usr/local/etc"
timestamp = DateTime.now
pf_anchors_dir = "#{pf_base_conf_dir}/pf_anchors"
macro_defs_file = "#{pf_base_conf_dir}/pf_macros.conf"
pf_conf = "/etc/pf.conf"
backup_data_dir = "/tmp/"
backup_file = "data.#{timestamp}"
backup = "#{backup_data_dir}/#{backup_file}"
if File.exists?( "#{macro_defs_file}" )
macro_definitions = IO.read("#{macro_defs_file}")
else
macro_definitions = nil
end
#first take care of pf.conf
FileUtils.copy( pf_conf, backup )
File.open( backup, "r" ) do |file|
new_file = File.open( pf_conf, "w" )
file.each do |line|
new_line = line.gsub( /^.*<--\[MACROS\]--\>.*$/, macro_definitions )
new_file.write new_line
end
file.close
FileUtils.rm( backup )
end
#then take care of the anchor files
Find.find(pf_anchors_dir) do |file_name|
Find.prune if file_name =~ /\.svn/
if File.file?(file_name)
FileUtils.copy( file_name, backup )
File.open(backup, "r") do |file|
new_file = File.open( file_name, "w" )
file.each do |line|
newline = line.gsub(/^.*<--\[MACROS\]--\>.*$/, macro_definitions )
new_file.write newline
end
file.close
FileUtils.rm( backup )
end
end
end
Posted in FreeBSD, OpenBSD, PF / CARP , Sysadmin | Tags Anchors, macros
Posted by Tres
Sun, 24 Dec 2006 04:11:34 GMT
Tables allow you to write abstract rulesets that can be manipulated on the fly. Adding and removing IP addresses from tables provides a simple interface for scripting the addition and removal of devices from your abstract rulesets.
The only problem, from a management standpoint, is that you’ve got to take care of IP addresses, not host names. But as long as your network addressing is sane, and you have a relatively stable set of machines that need access, you should be able to manage the address tables without much trouble.
However, if you don’t like the idea of taking care of IP addresses, you can easily script something that reads a file of names and creates a corresponding set of IP address table files. The following ruby script should take care of it:
#!/usr/bin/env ruby -w
require 'fileutils'
require 'socket'
require 'date'
require 'find'
pf_base_conf_dir="/usr/local/etc"
timestamp = DateTime.now
table_hostnames_dir = "#{pf_base_conf_dir}/pf_table_hostnames"
pf_table_dir = "#{pf_base_conf_dir}/pf_tables"
backup_file = "data.#{timestamp}"
Find.find(table_hostnames_dir) do |base_file_name|
Find.prune if base_file_name =~ /\.svn/
if File.file?(base_file_name)
FileUtils.copy( base_file_name, backup_file )
file_name_parts = split( base_file_name( /\// ))
table_file_name = file_name_parts[-1]
File.open(backup_file, "r") do |file|
new_file = File.open( "#{pf_table_dir}/table_file_name", "w" )
file.each do |line|
address = IPSocket.getaddress("line")
new_file.write address
end
file.close
FileUtils.rm( backup )
end
end
end
This script will dump all tables into a single directory, so you could effectively organize your tables in a logical hierarchy to match your anchors for human editing, and then have a single directory for all the production tables.
The only caveat here is, of course, you’ll need to have a dns entry for everything you intend to have in tables.
Posted in OpenBSD, PF / CARP , Sysadmin | Tags management, PF, Table | no comments
Posted by Tres
Tue, 19 Dec 2006 14:53:00 GMT
In order to set up static routes with OpenBSD at boot, all you need to do is add a normal “route add” line preceded by a ! to the /etc/hostname.if file that will be routing the traffic. The ! just tells OpenBSD to run this line as a command (so you can do practically anything you need to, not just set up routing).
Example
I want to set up a static route to the network 192.168.82.0/24 using the remote gateway 10.11.12.1. The interface being used is vlan1028. The parent interface for vlan1028 is em3. The IP address for the local router is 10.31.24.89/24.
/etc/hostname.vlan1028 will look like this:
10.31.24.89 netmask 255.255.255.0 broadcast 10.31.24.255 vlan 1028 vlandev em3
!route add -net 192.168.82.0/24 10.11.12.1
You can add as many route statements as you need, just make sure they are on different lines and each one is preceded by a !.
Posted in OpenBSD, Sysadmin | Tags boot, openbsd, route, static
Posted by Tres
Mon, 18 Dec 2006 16:30:00 GMT
Anchors not only provide a way to dynamically change PF rulesets on the fly, they are also a useful technique for organization of larger rulesets. If you’ve ever had to work with anywhere over 500 lines of PF rules, you know it’s manageable, but it’s cumbersome. And if you’ve ever had to share management of a PF ruleset with other administrators, you know that a single pf.conf makes management even more difficult. You also know it’s nearly impossible to manage multiple updates coming from different requesters at the same time with a single file. By breaking down the monolithic pf.conf into separate files, the ruleset is better suited for large numbers of rules and better suited for management by larger organizations with administrators who have varying levels of trust.
In essence, anchors allow you to separate a ruleset among many files, letting you write rules that can be dynamically loaded and unloaded from the firewall. This means you can do things like write a bunch of different rules for different required states, then have them automatically loaded and unloaded by cron. You could write rules that would be activated and deactivated by a junior-admin, or an application. Like all other great *nix tools, the possibilities are limited only by your imagination and need.
Dynamically changing firewall rules may not seem like much at first glance; after all, you can get the same effect from an edit and reload of rules. It’s true, with an edit and reload of rules, there’s no interruption in service, but it does require that a single firewall “manager” make edits to the pf.conf file and then, as root, reload the firewall rules. This process requires special skills and root level trust over the entire ruleset in order to make changes effective. In praxis, anchors provide finer granularity of control over different aspects of the ruleset. This level of granularity opens up a whole new set of tools and utilities that can be created for management and maintenance of the ruleset.
The functional benefits of anchors for a large organization are many, but the ability to organize rulesets into multiple files reduces the overhead involved with managing firewall rules significantly. When deciding how to break down your rules, you should think of rules the same way you would an OOP class; you’re trying to create an abstract encapsulation that will have the ability to act upon every state that the object can have. The fundamental goal here is to break things down into logical pieces that will be manipulable by other administrators. When starting out, you want to make the object types you’re working with as generic and abstract as possible. Each super-class should be used as a directory in which the rule sets will be placed. So if we can define mail_servers as a child of “public_servers,” we would create a directory labeled “public_servers” and put mail_rules into that directory. In turn, if “public_servers” can be a subclass of “servers,” we would create a directory for “servers,” then put “public_servers” as a subdirectory. If you’re using rule groups, these abstract super-classes will not only help in logical organization, they will allow you to define a more abstract set of rules that apply to all sub-classes.
You could logically order rules by interfaces (like vlan128_rules), by physical characteristics (like building_2213_rules), by roles (like student_rules), or by any other characteristic that will make the organization of the rules logical to the group that will manage them. I like to use anchors to break down rules logically by what type of service the rule is for. I also like to categorize the rules into “client” and “server” management groups so things are easier to find, and I don’t make any mistakes about what rules are being edited.
There’s two things that need to happen for an anchor to work. First, PF needs to know where to find the anchor file, and second PF needs to be told to use the anchor file. This may seem kind of redundant at first–and since our primary aim here is to discuss the use of anchors for ruleset management, it will seem redundant–but this separation allows the possibility of loading dynamic rules.
The practical function of an anchor within a pf.conf ruleset is to allow the inclusion of files other than pf.conf for reading into your firewall rules. It’s just like an include in C, or a require statement in Ruby; you’re just telling the server where to look for the definition once it sees it in the firewall. And just like an include or require statement, inclusion of the anchor file into the firewall ruleset doesn’t make anything happen. You’ve got to tell PF to use the anchor–just like calling a function or a class defined in another file.
Below is an example showing use of anchors. One of these files has our rules for allowing access to web servers. The other one has rules that allow access to our mail servers.
Step 1: Including an anchor file from pf.conf
This should be near the top of your pf.conf file. I define anchor files after I define queues.
man pf.conf says an anchor should look like this:
load anchor <name> from <file>
So, for our example, we would do something like this:
load anchor mail from /usr/local/etc/pf_anchors/servers/mail_rules
load anchor http from /usr/local/etc/pf_anchors/servers/web_rules
Step 2: Telling PF to use the included anchor
Telling PF to use the anchor means putting a reference to the anchor in the relevant section of pf.conf. That means nat-anchor directives should go into the NAT section of the ruleset, rdr-anchor directives go into the RDR section and anchor directives go with all the other filter rules.
nat-anchor mail
nat-anchor web
rdr-anchor mail
rdr-anchor web
anchor mail
anchor web
These represent three different sections of your pf.conf. You should make sure that any NAT, RDR or filter rules are placed into pf.conf appropriately. If you don’t PF will let you know it.
Posted in OpenBSD, PF / CARP , Sysadmin | Tags Anchors, large, management, rulest
Posted by Tres
Sun, 12 Nov 2006 09:41:00 GMT
OpenBSD has what is truly awesome system sensor integration.
Not only does it “just work” right out of the box, it also works for more hardware monitoring chipsets than any other *nix out there.
You can always check on current sensor status by using sysctl -a | grep sensor. Once you’ve got an idea of what’s being reported by your monitoring chipset, you can use sensorsd as the interface for monitoring.
Not only does sensorsd monitor these items and write to syslog, it can also be set up to run a script if there are problems found.
Example
We’re going to set up monitoring of a couple of different temperatures being monitored on our router. If there’s a problem found, we’ll have the script mail us.
-bash-3.1# sysctl -a | grep Temp
hw.sensors.24=lm2, Temp1, 39.00 degC
hw.sensors.25=lm2, Temp2, 30.50 degC
hw.sensors.26=lm2, Temp3, 33.00 degC
Use the hw.sensors.XX number to delineate the hardware sensor that will be monitored in sensorsd.conf. We want to monitor 24 and 25. On our hardware, 24 is the CPU sensor and 25 is the air intake sensor.
Here’s what /etc/sensorsd.conf looks like:
hw.sensors.24:high=60C:command=/root/scripts/senswarn.sh cpu_temperature %2 high %4
hw.sensors.25:high=32C:command=/root/scripts/senswarn.sh room_temperature %2 high %4
Now, if you check out man sensors.conf, it will give a pretty good explanation of what all this means. In short, what we’re doing is telling sensorsd to run /root/scripts/senswarn.sh if the temperature reaches above the high setting we’ve denoted in the conf file.
Here’s a look at /root/scripts/senswarn.sh
#!/bin/sh
PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin
notify="me@blas.phemo.us"
hostname=`hostname`
condition=$1
current=$2
tholds=$3
high=$4
low=$5
mailNotification() {
tholdString=$1
message="
This is an automatic message sent because the system monitor found the $condition
is not normal on $hostname.
The current $condition on $hostname is $current.
$tholdString
"
echo "$message" | mail -s "System Monitor Error: $condition on $hostname" $notify
}
if [ $tholds = "high" ]
then
if [ $current -ge $high ]
then
tholdString="The high threshold: $high"
mailNotification "$tholdString"
fi
fi
if [ $tholds = "low" ]
then
if [ $current -le $low ]
then
tholdString="The low threshold: $low"
mailNotification "$tholdString"
fi
fi
if [ $tholds = "both" ]
then
if [ $current -le $low ]
then
tholdString="
The low threshold: $low
The high threshold: $high
"
mailNotification "$tholdString"
fi
if [ $current -ge $high ]
then
tholdString="
The low threshold: $low
The high threshold: $high
"
mailNotification "$tholdString"
fi
fi
We’ve got additional checks in the script itself to verify the temperature is outside the bounds required because we’ve found that at when started, the sensorsd process will send a notification.
Finally, we add a section to rc.local to ensure that sensorsd is started on boot:
if [ -e /etc/sensorsd.conf ]
then
echo -n " sensorsd"; /usr/sbin/sensorsd
fi
Posted in OpenBSD | Tags monitor, temperature
Posted by Tres
Sat, 11 Nov 2006 06:26:00 GMT
We’ve got upwards of 30 vlans that we relay DHCP requests for. On FreeBSD, you just add your interfaces to a list in rc.conf and go. It makes things easy to maintain.
Out of the box OpenBSD has no analog to the shorthand method FreeBSD has, but it’s really easy to set up this functionality.
First we needed to create a bpf device for all the vlan interfaces that we were relaying across. To make bpf devices 10-30, use the following script:
#!/bin/sh
start=10
end=30
cd /dev
current=$start
while [ $current -le $end ]
do
./MAKEDEV bpf${current}
current=`expr $current + 1`
done
Then we set up /etc/rc.conf.local with the following:
dhcrelay_interfaces="vlan2 vlan3 vlan4 vlan5 vlan6 vlan7 vlan8 vlan9 vlan10 vlan11"
dhcrelay_servers="server1.blas.phemo.us server2.blas.phemo.us server3.blas.phemo.us"
Finally, we set up rc.local like this:
. /etc/rc.conf.local
if [ -n "${dhcrelay_interfaces}" ]
then
for i in $dhcrelay_interfaces
do
echo -n " dhcrelay $i:"; /usr/sbin/dhcrelay -i $i $dhcrelay_servers
done
fi
Now maintaining all those relay interfaces is as easy as it is in FreeBSD.
Posted in FreeBSD, OpenBSD, Sysadmin | Tags dhcprelay, openbsd | no comments