Total Pageviews

Search: This Blog, Linked From Here, The Web, My fav sites, My Blogroll


26 July 2010

OpenBSD --- An Overview of /etc

The /etc directory is the heart of any UNIX-like operating system. /etc contains the files that tell the system how it works, what it does, and how it behaves under any circumstances. The first thing one do on any unfamiliar UNIX breed is check out the /etc directory and see what make it tick; it's like kicking the tires and checking under the hood of a used car before taking it for a test drive.

One of the best ways to earn your journeyman grade in systems administration is read everything in /etc(of almost any UNIX system) and explain what it does, you have a good grip on the next rung up in the professional ladder.


Understanding /etc is especially important when upgrading OpenBSD, as /etc must be updated to include files and entries from the new version.
    In many cases the contents of existing files change, so you must understand what the files do in order to make proper decisions on what should be edited and what should be completely replaced.
    While mergemaster(8) will help identify files that have been added or changed, the actual decision-making process cannot be automated.
    We are going to discuss in depth the general-purpose files that are in use in almost every system, however, as well as some files that System V and Linux users probably haven't encountered before.

The first time you run adduser(8), it uses your answers to build its configuration file, /etc/adduser.conf. Value assignments in this file control adduser(8)'s behavior.
    If the variable has multiple legitimate values, those values are surrounded by parentheses. Without further ado, here are the standard things you may set in /etc/adduser.conf. To get a complete list of things that may be set in adduser.conf, you'll need to read the adduser script.
  • verbose = 1  The verbose flag tells adduser how much detail to give. If you have a verbose of 0, adduser(8) will only present a minimum of information when run. It will assume that you know it is checking the user files in /etc/, for example, and hence not bother to tell you about them. The standard is 1. If you want to debug the adduser program itself, you can set this to 2 for maximum debugging output. I habitually turn this to 0 without a second thought.
  • encryptionmethod = "blowfish"  OpenBSD supports a variety of encryption schemes for encoding passwords. Blowfish is the OpenBSD standard. If you want to share your password file with other UNIX-like operating systems, though, set this to "old" to get DES hashes.
  • dotdir = "/etc/skel"  All new user accounts get a set of default shell dotfiles. You can use the ones that OpenBSD provides in /etc/skel, or you can create your own customized for your environment. Any files in this directory will be copied to the user's home directory, so you can also use this to distribute any other files you like. Be sure that regular users cannot put "extras" in a directory you specify!
  • send_message = "no"  On many operating systems, new users automatically receive a welcome or instructional email message. By default, OpenBSD does not do this. If you put the full path to a file in this variable, however, the contents of that file will be emailed to each new user. If you set this to no, a message will not be sent. OpenBSD does have a default new user message in /etc/adduser.message, but you should feel free to create your own. The adduser message accepts the variables $username and $fullname; this allows you to customize your welcome message somewhat. (If you're familiar with Perl, you can add your own variables by editing /usr/sbin/adduser.) If you wish, go ahead and create your own message instead of using the brief and generic default. I generally use an /etc/adduser.message.local somewhat like this:
    Welcome to The Company.
    Help is available at 800-555-1212, or online at
    Use of this account is governed by our acceptable use policy,
    available at or on this system in
    Thank you for your business. We look forward to serving you.
    The Company Support Staff.
  • logfile = "/var/log/adduser" Adduser will record the history of its actions in the file specified here.
  • home = "/home"  This variable controls the directory where users' home directories are located. This is one of the first things I take care of on any OpenBSD system. If you do not specifically create a /home partition, the default will place users' home directories on the root partition. This is bad, for a variety of reasons. The biggest problem in that your root partition is limited to 8GB in size, which greatly restricts the amount of user data your system can hold. If you expect to have a lot of user accounts on your system (i.e., for a web server), you almost certainly want a /home partition so you can mount it with the appropriate permissions. If you only have systems administrators accounts on this system, you might want to place user accounts under /usr/home and create a symlink from /home. Both work, but you should know about your choices.
  • path = ('/bin', '/usr/bin', '/usr/local/bin')  This contains the list of directories that can contain legitimate shells. This covers most standard situations, but if you find that you're installing shells in some unusual location, you'll want to edit this appropriately.
  • shellpref = ('csh', 'sh', 'ksh', 'nologin')  This is a list of legitimate shells. Adduser will let you choose from any of these when creating a new user.
  • defaultshell = "ksh"  This is the default user shell. It can be any of the shells listed in "shellpref."
  • defaultgroup = USER  This is the primary group that the user is a member of. Traditional BSD systems assign each user to a group of the same name as the username. For example, our "phil" user is automatically a member of the group "phil," which was created just for him. You might want all users to be part of a separate group, such as "students" or "customers." If that's the case, you can set that on this line. You can add this user to other groups manually, but this will be the primary group.
  • uid_start = 1000 uid_end = 2147483647  These give the range of acceptable user ID numbers(uids). The default is fine for most cases, but you might want to use different numbers to interoperate with your other UNIX-like systems. 

OpenBSD supports AFS, a distributed file system much like NFS. If you're interested in setting up AFS, check out afsd.conf(8).

The automounter daemon automatically loads NFS file systems upon request. If you're interested in using this function, check out amd(8).

This directory contains the configuration for packet filter authentication.

All PF features are configured in /etc/pf.conf. You're going to be very good friends with this file before we're through, but we'll start with an overview.
    The /etc/pf.conf file contains statements and rules, whose format varies with the feature they configure.
As the PF features manipulate packets in very specific ways, not only is the order of rules extremely important but also the order in which the features are configured matters greatly. If you try to do stateful inspection before you reassemble packet fragments, for example, things will not work properly.
The default /etc/pf.conf has the sample rules in order by feature, but if you're in the slightest danger of becoming confused, I suggest that you put large comment markers between them, in capital letters if necessary. (Use standard pound signs to comment /etc/pf.conf.) The features must (Technically, macros and tables can appear anywhere in the rules, as long as they are defined before they are used — but scattering macros and tables throughout your ruleset is a good way to confuse yourself!) be entered in /etc/pf.conf in this exact order:
Traffic normalization
Bandwidth management
Redirection Packet filtering

No matter what section a particular rule may be in, it will have this general format:
pass in on fxp0 proto tcp from any to port 22 keep state

  1. The first word(pass) is a keyword labeling what sort of rule this is. Each sort of rule has its own keywords. This particular rule is a packet-filtering rule. 
  2. "in" is the direction the packet is traveling. 
  3. "on fxp0" labels which interface this packet is crossing. The remainder of the rule line varies with the sort of rule it is. This particular example happens to be a packet-filtering rule. Two keywords that appear in many sorts of PF rules are "in" and "out." When you're building a firewall, the word "in" usually means "traffic coming into the protected network," and "out" means "traffic leaving the protected network." Your OpenBSD system does not magically know which side of your network is protected and which is not. As far as your packet filter is concerned, it is just controlling traffic from one interface to another. The keyword "in" means traffic flowing into the machine from the network," while "out" means "traffic leaving the machine for the network." When you see the word "in" or "out" in a PF rule, do not think about your network as a whole. Imagine that you're very small and sitting on your CPU, and watching packets enter and leave the computer. You cannot see what lies beyond the computer case, just the packets as they come and go. Packets marked with an "in" are coming toward you, while packets marked with "out" are leaving.
"My Network Can Do No Wrong"
While we're on the subject of which way is in and which is out, let's spend a moment and ponder in and out of the network as a whole. Many network administrators who build a firewall carefully filter and restrict incoming traffic, but only apply minimal restrictions on outgoing traffic.
While control of incoming traffic is among the most in-your-face issues of network management, control of outgoing traffic is also quite important. Even if you trust your users, viruses or Trojans can convert a salesperson's workstation into a garbage-spewing pest. Do not assume that your network can do no wrong — it can be malicious, and one day it will, but careful traffic control can minimize the damage you will inflict upon your neighbors, clients, and customers. 
And believe me; even if the system that wreaks havoc is the Windows 98 workstation that a senior company officer refuses to give up, the mayhem it causes will be considered the fault and responsibility of the network administrator.

Logical Operators
Many application protocols use a range of network ports, or you may want rules that apply to a particular group of hosts with one or two exceptions. FTP, for example, is notorious for connecting over random high-numbered ports. PF makes it easy to specify ranges and groups by including a variety of logical operators.
In the examples here we're going to look at some sorts of rules you haven't yet seen, but don't let that worry you. Just keep the logical operator examples in mind as we go on.
= Equals exactly this (default)
!= Does not equal this
< Is less than
<= Is less than or equal to
> Is greater than
>= Is greater than or equal to this
>< Anything between two numbers, exclusive
<> Anything outside two numbers, exclusive
The equal symbol is the implicit default in PF rules. Our previous example could have been written like this:
pass in proto udp from port = 53 to port  = 53

Note the equal signs in the middle of the port declaration. This makes absolutely no functional difference, but some people find such rules more readable.
    The not-equal symbol can be used to exclude a port, host, or interface from a rule. For example, here we allow traffic to enter the system from any interface except fxp3:

pass in on !fxp3 from any to any

We could also block traffic from going to particular ports. Here, we allow the world at large to connect to any service on this machine except SSH. (In most cases you would write a block rule instead, but this is certainly a legitimate way of doing it.)

pass in from any to port != 22

The other logical operators all apply only to port numbers. The > (greater than) and >= (greater than or equal to) operators can be used to specify a port above a certain range. Either can be used in most situations. For example, both of the following rules allow any packets to a port numbered 1024 or greater to pass:

pass in proto tcp from any to any port > 1023
pass in proto tcp from any to any port >= 1024

Similarly, you could prevent anyone with a UID 1100 or greater to make outbound connections. This can be helpful if you give your system administrators and trusted users a UID less that 1100, and untrusted users and customers higher UIDs.
block out proto tcp from any to any user >= 1100
You can also specify a range of ports with the "><" operator. This takes two arguments, the low port number and the high port number. This following rule allows TCP traffic on any port above 5000 but below 6000. Port 0 through 5000 will not be allowed, and ports 6000 or greater will also be rejected.
pass in proto tcp from any to any port 5000><6000

The "<>" operator matches ports that are not within a specific range. The following example allows access to TCP ports 0 through 5000, and ports 6000 and greater:

pass in proto tcp from any to any port 5000<>6000

Combining Entries with Braces
You may have a regular pattern of rules for certain hosts or ports. Perhaps you want a particular group of TCP ports open to a particular group of hosts, and your rule entries would just be repetitions with one minor change on each rule. Opening port 80 and 443 to a server requires two rules. For example, a set of 30 web servers means you have 60 rules that are almost identical.
    Curly braces allow you to write these rules briefly and efficiently, thereby greatly reducing the risk of misconfigurations. (Again, while some of these examples make reference to rules that we haven't discussed yet, keep these examples in mind as we go on.)
    Each entry within the braces creates a separate rule. This is easier to understand by example. For example, DNS queries run over UDP port 53, while zone transfers run over TCP port 53. You could write a UDP port 53 rule and a TCP port 53 rule like this:

pass out proto udp from any to any port 53
pass out proto tcp from any to any port 53
These rules are almost identical, with the exception of the UDP and  TCP keywords, so you can combine them with braces:

pass in proto {tcp, udp} from any to any port 53

When the PF rule parser examines this entry, it will automatically expand it into a set of rules. You only have to write one rule, which is easier to maintain than two.

pass in proto tcp from any to any port = domain
pass in proto udp from any to any port = domain

While this example is trivial, it quickly becomes quite useful when you have a large number of hosts with similar rules.
    You can use multiple braces within a line. Suppose that you have two web servers, and, that need clients to access them on ports 80 and 443. Two servers, two ports, for a total of four rules. You could write rules for both protocols and both servers, much like this:

pass in from any to port 80
pass in from any to port 443
pass in from any to port 80
pass in from any to port 443

There's nothing wrong with this, but you can write the rule a little more easily using braces. The previous rules compress down to this:

pass in proto tcp from any to {,} port {80,443}

Again, when you load your PF rules into the kernel, the line above will be expanded to the full number of rules.

    No comments:

    Post a Comment