Small server IPv4/IPv6 pf.conf

I’m deploying IPv6 for my employer. While getting corporate servers up on IPv6 is nice and all, of course I put priority on my own personal Web server.

Just because IPv6 is still populated mostly by early adopters, doesn’t mean we can neglect basic system security. That means that the server needs a packet filter for both IPv4 and IPv6. PF supports filtering both protocols in one ruleset.

The following is a unified IPv4/IPv6 PF ruleset for a small server. It:

  • Allows all traffic from management addresses
  • Allows all ICMP and ICMPv6 traffic
  • Allows traffic to specific ports where we choose to provide service — in this case, SMTP, DNS, and HTTP.
  • Blocks everything else.

    Fill in the IPv4 and IPv6 external addresses, define your interface, adjust the permitted services to match your environment, and you’re ready to go.

    ext_if="em0"
    ext_addr="{192.0.2.40, 192.0.2.41}"
    ext_v6="2001:db8:0:12::2"

    table <mgmt_hosts> const {172.16.0.0/24, 172.16.5.0/24}
    table <v6_mgmt_hosts> const {2001:db8:1:4::2}

    set block-policy return
    set loginterface $ext_if
    set skip on lo0

    scrub in all no-df

    block in all

    pass in on $ext_if proto icmp all
    pass in on $ext_if proto icmp6 all

    pass in on $ext_if inet from <mgmt_hosts>
    pass in on $ext_if inet6 from <v6_mgmt_hosts>

    pass out on $ext_if inet from $ext_addr to any
    pass out on $ext_if inet6 from $ext_v6 to any

    #services we permit
    pass in on $ext_if proto tcp from any to $ext_addr port {25,53,80}
    pass in on $ext_if proto udp from any to $ext_addr port 53
    pass in on $ext_if inet6 proto tcp from any to $ext_v6 port {53,80}
    pass in on $ext_if inet6 proto udp from any to $ext_v6 port 53

  • Print pre-order for “SSH Mastery” now available

    The OpenBSD folks have made pre-orders available for SSH Mastery.

    I’m giving the books to the OpenBSD Project at cost, and they’re selling them at list as a fund-raiser. I make nothing on books ordered through OpenBSD, but the money will go to further OpenBSD, OpenSSH, PF, and who knows what else. I’m going to imagine that the money will support the annual developer barbeque, as buying beer is more fun than buying hardware.

    I will make a decent profit on books sold through Amazon, Barnes & Noble, and brick-and-mortar stores. (Yes, I can get books into brick-and-mortar stores, with a bit of luck, a smidgeon of effort, and just a few ounces of blackmail.) I figure it’ll even out; the general public will order from Amazon.

    When will the books arrive? Once the proofs are approved, I’ll order the OpenBSD books before I approve sale through Amazon. I don’t know when that is yet, but believe me, I want this book out there.

    So, if I make nothing on this, why do it? It’s a good way to support a widely-used project that has written software that makes my job easier. So order yours now!

    Plus, I write about open-source software projects, preferably BSD-based ones. This means that I have to maintain good relationships with those projects. Not only am I a geek, I work at home. My usual social interactions consist of ignoring the threatening emails from the boss, the pet rats asking for treats, and the nagging phone calls from the social worker asking if I’ve taken my meds today. As you might guess, maintaining good relationships is not my strong point. If you have trouble keeping friends, try bribery. I hear it works a treat.

    Installing WHMCS on FreeBSD 9.0-RELEASE

    Or, if you prefer: “WHMCS versus PHP.” Blogged for the next sysadmin searching Google.

    $DAYJOB recently acquired WHMCS to help automate virtual server provisioning, billing, and so on. According to everything I’ve read, WHMCS runs just fine on FreeBSD, so I installed the prerequisites on a 9.0-i386 machine. As with any server for PHP-based Web sites, I verified that the server processed PHP with a simple phpinfo() page. I then grabbed the WHMCS tarball (no link, you must be a customer, sorry), extracted it into the directory, ran the setup program, fed in the database information and license key…

    ..and it wouldn’t run. Calling up the app resulted in a blank page. WHMCS provides troubleshooting instructions for this exact circumstance. I enabled the requested debugging, but couldn’t get WHMCS to produce an error. Adding a bogus argument to my phpinfo() test page made an error appear, so I was confident the failure to display an error message wasn’t a server configuration problem.

    This comes down to FreeBSD’s PHP packaging.

    When you install PHP on the popular varieties of Linux, you generally get a whole slew of PHP extensions with it. BSD-based systems only install exactly what you ask for: if you want PHP but don’t request any extensions, you won’t get any extensions.

    I agree with this approach. Every piece of installed software needs patching and updating. Every piece of installed software is a potential attack vector. If I don’t need a piece of software, I don’t want it on my server.

    WHMCS doesn’t list all of the required extensions. They assume you have a kitchen-sink PHP install. After some reading and research, I found that WHMCS runs fine with the following PHP modules and extensions installed. I’ve included the version numbers for reference, but you should be able to just pkg_add -r all of these by name.

    php5-5.3.8
    php5-bz2-5.3.8
    php5-ctype-5.3.8
    php5-curl-5.3.8
    php5-dom-5.3.8
    php5-extensions-1.6
    php5-filter-5.3.8
    php5-gd-5.3.8
    php5-hash-5.3.8
    php5-iconv-5.3.8
    php5-json-5.3.8
    php5-ldap-5.3.8
    php5-mysql-5.3.8
    php5-openssl-5.3.8
    php5-pdo-5.3.8
    php5-pdo_sqlite-5.3.8
    php5-phar-5.3.8
    php5-posix-5.3.8
    php5-session-5.3.8
    php5-simplexml-5.3.8
    php5-tokenizer-5.3.8
    php5-xml-5.3.8
    php5-xmlreader-5.3.8
    php5-xmlwriter-5.3.8
    php5-zip-5.3.8
    php5-zlib-5.3.8

    I’d really like to trim this down to only what is strictly necessary to run WHMCS, but that information doesn’t seem to be available. I could methodically remove and reinstall extensions to see when WHMCS breaks, but I have better things to do than debug missing docs for a commercial PHP app.

    On the plus side: now that WHMCS is installed, it’s really slick. I’m looking forward to using it. Actually, I’m looking forward to having other people use it for me, so I can do more interesting things than provision servers, accounts, and billing.

    New review of SSH Mastery, and print pre-order status

    There’s a new review of SSH Mastery over at DragonFlyBSD Digest. I’m delighted that Justin liked the book. (Mind you, I’m appalled that he’s actually reading and paying attention to the minutia I occasionally post here. But I’m delighted he liked the book.)

    On the pre-order front: Austin Hook just ordered 200 copies of SSH Mastery for the OpenBSD Project. He will be listing the book for pre-order “soon.” I’ve given them the greatest discount possible, and they’ll be selling the book for list price. Proceeds will go to support OpenBSD/OpenSSH development. I will fill Austin’s order at the first opportunity.

    When is that? When the book exists in finished form. I reviewed the print layout today, made some corrections, and sent them back to the layout person. If she doesn’t kill me outright, I’ll be able to order proofs in a few days. If the proofs show an error, I do another cycle. (Print pages look nothing like on-screen pages.) Once I approve the proofs, I can order books.

    A normal publisher (whatever that means) would have a scheduled print time. They’d push out the release date, and delay the book if necessary to fit that window. That gives them a known release date. Me, I’m not going to set a sufficiently-padded arbitrary date when I can get them sooner.

    And for those of you who wonder when I’m going to quit pushing my wares and post techie stuff again, I’ll have a post on DNSSEC deployment next week.

    SSH Mastery available at Smashwords

    To my surprise, SSH Mastery is available at Smashwords.

    I don’t know if this version will make it through to Kobo and iBooks, but you can buy it now. If I have to update it to get the book through the Smashwords Meatgrinder and into third-party stores, you’d get access to those later versions as well.

    enable DNSSec resolution on BIND 9.8.1

    With BIND 9.8, enabling DNSSec resolution and verification is now so simple and low-impact there’s absolutely no reason to not do it. Ignore the complicated tutorials filling the Internet. DNSSec is very easy on recursive servers.

    DNS is the weak link in Internet security. Someone who can forge DNS entries in your server can use that to leverage his way further into your systems. DNSSec (mostly) solves this problem. Deploying DNSSec on your own domains is still fairly complicated, but telling a BIND DNS server to check for the presence of DNSSec is now simple.

    In BIND 9.8.1 and newer (included with FreeBSD 9 and available for dang near everything else), add the following entries to your named.conf file.

    options {
    ...
    dnssec-enable yes;
    dnssec-validation auto;
    ...
    };

    This configuration uses the predefined trust anchor for the root zone, which is what most of us should use.

    Restart named. You’re done. If a domain is protected with DNSSec, your DNS server will reject forged entries.

    To test everything at once, configure your desktop to use your newly DNSSec-aware resolver and browse to http://test.dnssec-or-not.org/. This gives you a simple yes or no answer. Verified DNSSec is indicated in dig(1) output by the presence of the ad (authenticated data) flag.

    For the new year, add two lines to your named.conf today. Get all the DNSSec protection you can. Later, I’ll discuss adding DNSSec to authoritative domains.

    SSH Mastery Cover Photo

    Last summer, preparing for the OpenSSH book, I attended a course on being your own publisher. If you’re interested in publishing, I highly recommend the Think like a Publisher course. The hotel was decorated with a variety of nautical clutter.

    This critter hung directly over the breakfast table.

    A Real Blowfish
    The Hand of Karma

    This was obviously the Hand of Fate. I borrowed a couple of really good cameras from fellow workshop attendees and snapped a bunch of photos. I’m a lousy photographer, but with good equipment and enough tries, eventually one came out.

    The cover artist has assured me he can strip out the background and arrange this real-life Puffy suitably.

    Dec 2011 Updates

    The OpenSSH book is in copyedit. I hope to get the copyedits back this year. I’ve seen the first round of copyedits, and they don’t look too bad. Once I make the corrections, the book goes to the print-on-demand layout person and I start on the ebook conversion. The ebook should be out next month.

    The best title I’ve had suggested was “SSH: You’re Doing It Wrong.” I love that title, but it’s not really appropriate. Instead, it’ll be “SSH Mastery: OpenSSH, PuTTY, Tunnels, and Keys.” That’s what the book is about, after all.

    Progressing on Absolute OpenBSD 2 slowly, thanks to the holidays.

    sudo auth via ssh-agent

    One of the nicest things about writing a book is that your tech reviewers tell you completely new but cool stuff about your topic. While I was writing the OpenSSH book, one of the more advanced reviewers mentioned that you could use your SSH agent as an authentication source for sudo via pam_ssh_agent_auth.

    I have dozens of servers. They all have a central password provider (LDAP). They’re all secured, but I can’t guarantee that a script kiddie cannot crack them. This means I can’t truly trust my trusted servers. I really want to reduce how often I send my password onto a server. But I also need to require additional authentication for superuser activities, so using NOPASSWD in sudoers isn’t a real solution. By passing the sudo authentication back to my SSH agent, I reduce the number of times I must give my password to my hopefully-but-not-100%-certain-secure servers. I can also disable password access to sudo, so that even if someone steals my password, they can’t use it. (Yes, someone could possibly hijack my SSH agent socket, but that requires a level of skill beyond most script kiddies and raises the skill required for APT.)

    My sample platform is FreeBSD-9/i386, but this should work on any OS that supports PAM. OpenBSD doesn’t, but other BSDs and most Linuxes do.

    pam_ssh_agent_auth is in security/pam_ssh_agent_auth in ports and pkgsrc. There are no build-time configuration knobs and no dependencies, so I used the package.

    While that installs, look at your sudoers file. sudo defaults to purging your environment variables, but if you’re going to use your SSH agent with sudo, you must retain $SSH_AUTH_SOCK. I find it’s useful to retain a few other SSH environment variables, for sftp if nothing else.

    Newer versions of sudo cache the fact that you’ve recently entered your password, and let you run multiple sudo commands in quick succession without entering your password. This behavior is fine in most environments if you’re actually typing your password, but as sudo will now query a piece of software for your authentication credentials, this behavior is unnecessary. (Also, this caching will drive you totally bonkers when you’re trying to verify and debug your configuration.) Disable this with the timestamp_timeout option.

    To permit the SSH environment and set the timestamp timeout, add the following line to sudoers:

    Defaults env_keep += "SSH_AUTH_SOCK",timestamp_timeout=0

    You can add other environment variables, of course, so this won’t conflict with my earlier post on sftp versus sudo.

    Now tell sudo to use the new module, via PAM. Find sudo’s PAM configuration: on FreeBSD, it’s /usr/local/etc/pam.d/sudo. Here’s my sudo PAM configuration:

    auth sufficient /usr/local/lib/pam_ssh_agent_auth.so file=~/.ssh/authorized_keys
    auth required pam_deny.so
    account include system
    session required pam_permit.so

    By default, sudo uses the system authentication. I removed that. I also removed the password management entry. Instead, I first try to authenticate via pam_ssh_agent_auth.so. If that succeeds, sudo works. If not, the auth attempt fails.

    Now try it. Fire up your SSH agent and load your key. SSH to the server with agent forwarding (-A), then ask sudo what you may run.

    $ sudo -l
    Matching Defaults entries for mwlucas on this host:
    env_keep+="SSH_CLIENT SSH_CONNECTION SSH_TTY SSH_AUTH_SOCK",
    timestamp_timeout=0

    Runas and Command-specific defaults for mwlucas:

    User mwlucas may run the following commands on this host:
    (ALL) ALL
    (ALL) ALL

    Now get rid of your SSH agent and try again.

    $ unsetenv SSH_AUTH_SOCK
    $ sudo -l
    Sorry, try again.
    Sorry, try again.
    Sorry, try again.
    sudo: 3 incorrect password attempts

    The interesting thing here is that while you’re asked for a password, you never get a chance to enter one. Sudo immediately rejects you three times. Your average script kiddie will have a screaming seizure of frustration.

    The downside to this setup is that you cannot use passwords for sudo on the console. You must become root if you’re sitting in front of the machine. I’m sure there’s a way around this, but I’m insufficiently clever to come up with it.

    Using the SSH agent for sudo authentication changes your security profile. All of the arguments against using SSH agents are still valid. But if you’ve made the choice to use an SSH agent, why not use it to the fullest? And as this is built on PAM, any program built with PAM can use the SSH agent for authentication.