Total Pageviews

Friday 28 December 2012

FreeBSD portsnap

Secure FreeBSD ports tree updating

Portsnap is a system for securely downloading and updating a compressed snapshot of the FreeBSD ports tree, and using this compressed snapshot to extract or update a (uncompressed) copy of the ports tree. Historically, most people have used CVSup to keep their ports tree up to date, but CVSup has a number of limitations:
  • CVSup is insecure. The protocol uses no encryption or signing, and any attacker who can intercept the connection can insert arbitrary data into the tree you are updating.
  • CVSup isn't end-to-end. Related to the previous point, this means that anyone who can compromise a CVSup mirror can feed arbitrary data to the people who are using that mirror.
  • CVSup isn't designed for frequent small updates. While CVSup is very good at distributing CVS trees, and is very efficient for updating a tree which has been significantly changed (eg, by a month or more of commits), it transmits a list of all the files in the tree, which makes it quite inefficient if only a few files have changed.
  • CVSup uses a custom protocol. This can cause problems for people behind firewalls -- outgoing connections on port 5999 need to be permitted -- and it needs a heavyweight server (cvsupd).
Portsnap avoids these problems by operating over HTTP (using FreeBSD's fetch(1) utility and a new experimental pipelined HTTP client), signing the snapshots using OpenSSL, and using more sophisticated delta compression to distribute the snapshots. In order to compare the bandwidth usage of cvsup and portsnap for frequent updates of the FreeBSD ports tree, I used each method to update across a 58-hour period from 12:15 AM on January 13th, 2005 to 10:15 AM on January 15th, 2005. While cvsup used 6388kB of bandwidth (2418kB up, 3969kB down), portsnap only used 370kB (108kB up, 262kB down) -- an improvement of over a factor of 17. In addition, cvsup used 212 seconds of cpu time compared to portsnap's 32 seconds of cpu time -- a difference of over a factor of six -- and 534 seconds of wall-clock time compared to portsnap's 75 seconds of wall-clock time (but since the wall-clock time depends upon network congestion and server loads, it isn't particularly significant).
Portsnap stores a compressed snapshot of the ports tree (around 40 MB) on disk, by default in /usr/local/portsnap. This compressed snapshot can then be extracted as needed (eg, into /usr/ports).
Portsnap is in the FreeBSD base system for all versions from 5.5 upwards (including 6.0, which was released before 5.5); users of earlier FreeBSD releases can install portsnap from the ports tree (sysutils/portsnap).
I have a nice portsnap usage graph showing the number of systems running each version of portsnap (as approximated by the updates they fetch).

Usage

  1. Install sysutils/portsnap from the FreeBSD ports tree.
  2. To fetch a compressed snapshot, or update your current compressed snapshot, run `portsnap fetch`.
  3. To extract the ports tree, run `portsnap extract`.
  4. After extracting a ports tree, to update it to reflect changes in the compressed snapshot, run `portsnap update` -- this is much faster than `portsnap extract` because it avoids extracting directories which haven't changed.
Please note that when extracting a copy of the FreeBSD ports tree, portsnap will remove existing files. If you have any local changes (eg, extra patches which you've added into a port's files/ directory) then you'll have to put those back after updating the ports tree。

FROM http://www.daemonology.net/portsnap/