<?xml version="1.0" encoding="UTF-8"?>

<rdf:RDF
 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 xmlns="http://purl.org/rss/1.0/"
 xmlns:content="http://purl.org/rss/1.0/modules/content/"
 xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
 xmlns:dc="http://purl.org/dc/elements/1.1/"
 xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
 xmlns:admin="http://webns.net/mvcb/"
>

<channel rdf:about="http://www.martini.nu/blog/index.html">
<title>martini :: blog</title>
<link>http://www.martini.nu/blog/index.html</link>
<description>First came the bad mousie, then the one bird. Then the LION, that ate me like a sandwich.</description>
<dc:language>en</dc:language>
<dc:rights>Creative Commons</dc:rights>
<dc:date>2013-05-23T15:23:54Z</dc:date>
<dc:creator>mahlon@martini.nu</dc:creator>
<items>
 <rdf:Seq>
  <rdf:li rdf:resource="http://www.martini.nu/blog/2012/07/hg-house-in-order.html" />
  <rdf:li rdf:resource="http://www.martini.nu/blog/2010/06/tor-vbox.html" />
  <rdf:li rdf:resource="http://www.martini.nu/blog/2010/05/rest-doing-it-wrong.html" />
  <rdf:li rdf:resource="http://www.martini.nu/blog/2010/05/scp-petpeeves.html" />
  <rdf:li rdf:resource="http://www.martini.nu/blog/2010/01/freebsd-pxe-grub.html" />
  <rdf:li rdf:resource="http://www.martini.nu/blog/2009/08/gadget.html" />
  <rdf:li rdf:resource="http://www.martini.nu/blog/2009/08/bootlegger.html" />
  <rdf:li rdf:resource="http://www.martini.nu/blog/2008/12/sales.html" />
  <rdf:li rdf:resource="http://www.martini.nu/blog/2008/11/mobile_1.html" />
  <rdf:li rdf:resource="http://www.martini.nu/blog/2008/10/ps3-pf.html" />
 </rdf:Seq>
</items>
</channel>
<item rdf:about="http://www.martini.nu/blog/2012/07/hg-house-in-order.html">
<title>Get your house in order with Mercurial</title>
<link>http://www.martini.nu/blog/2012/07/hg-house-in-order.html</link>
<description>&#x3C;p&#x3E;At some point in the last few years, I migrated all my code over to
&#x3C;a href=&#x22;http://mercurial.selenic.com/&#x22;&#x3E;Mercurial&#x3C;/a&#x3E;, and basically never looked
back.&#x3C;/p&#x3E;

&#x3C;p&#x3E;In addition to code, I&#x27;ve also always maintained separate machine
repositories, housing configuration files for miscellaneous colocation
servers and home systems -- basically, anything that would consume
a bunch of my time to rework from scratch.  Make a change to
something in &#x3C;em&#x3E;/etc&#x3C;/em&#x3E;?  Copy and commit it to the repo, with a
comment on what warranted the change.  Poor man&#x27;s configuration
management.  (Side note: If you have &#x3E; 1 machines and aren&#x27;t at
least doing this much with config files in ANY &#x3C;a href=&#x22;http://en.wikipedia.org/wiki/Revision_control&#x22;&#x3E;version control
system&#x3C;/a&#x3E;, why not?)&#x3C;/p&#x3E;

&#x3C;p&#x3E;This was obviously pretty far from foolproof, and horribly inefficient.
What if I forgot to copy a modified file?  If a machine needed
rebuilding, how best to deploy the configs in the repo back to the
system?&#x3C;/p&#x3E;

&#x3C;p&#x3E;The problem grew when I started tracking my home directory.  Far more
files to manage, and I wanted a &#x22;base&#x22; set of config files that were
slightly different on each of the machines I work on.  Branching per
workstation seemed the best method to initially deal with this, but I
soon found myself spending far too much time in branch merges, rsyncing
from repo to homedir and back, and writing helper scripts.  There&#x27;s
gotta be a better way!&#x3C;/p&#x3E;

&#x3C;p&#x3E;Yeah, there totally is.&#x3C;/p&#x3E;

&#x3C;h2&#x3E;Machine configuration&#x3C;/h2&#x3E;

&#x3C;p&#x3E;The trick with both machine configuration and homedir management lies in
exploiting Mercurials &#x22;directory walking&#x22; to find a repository.  If
you&#x27;re currently in &#x3C;em&#x3E;/usr/local/etc&#x3C;/em&#x3E; and run an &#x3C;strong&#x3E;hg&#x3C;/strong&#x3E; command,
Mercurial checks for a repository in &#x3C;em&#x3E;/usr/local/etc&#x3C;/em&#x3E;, then
&#x3C;em&#x3E;/usr/local&#x3C;/em&#x3E;, then &#x3C;em&#x3E;/usr&#x3C;/em&#x3E;, then &#x3C;em&#x3E;/&#x3C;/em&#x3E;.  It stops as soon as it finds one.&#x3C;/p&#x3E;

&#x3C;p&#x3E;This means that if you initialize a new repository at the root of the
filesystem, Mercurial will &#x3C;strong&#x3E;always&#x3C;/strong&#x3E; find a repository, no matter where
you&#x27;re at.  If you&#x27;re actually working in a &#x22;regular&#x22; code repository
elsewhere in the filesystem, Mercurial will see that first, so it
behaves exactly as you&#x27;d expect it to.&#x3C;/p&#x3E;

&#x3C;p&#x3E;Doing something like an &#x27;hg stat&#x27; is of course very slow when walking
an entire machine, so there&#x27;s a second trick -- an &#x3C;strong&#x3E;.hgignore&#x3C;/strong&#x3E; file
that tells Mercurial to ignore everything by default.  With this file in
place, Mercurial just steps aside -- &#x3C;em&#x3E;hg&#x3C;/em&#x3E; commands only operate on explicitly
added files, and it&#x27;s super quick.&#x3C;/p&#x3E;

&#x3C;p&#x3E;A new machine repository is setup like so:&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;$ cd /
$ sudo hg init
$ echo &#x27;.*&#x27; | sudo tee .hgignore
$ sudo hg add .hgignore
$ sudo hg commit -u Mahlon -m &#x22;Initial commit of `hostname` repository&#x22;
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;And that&#x27;s it.  You&#x27;ll have to be root to add files to or edit the repo.
When there&#x27;s something you want to track, just &#x3C;strong&#x3E;hg add&#x3C;/strong&#x3E; it and commit.
Even better, a backup of the important config files on a machine just
becomes a simple:&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;$ cd /tmp; sudo hg bundle -a `hostname -s`.bndl
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;Or from a remote machine:&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;$ hg clone ssh://root@example.com// example.com
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;Redeploying configs to a fresh system has a few small, but arguably
unintuitive additional steps.  Mercurial is &#x3C;em&#x3E;careful&#x3C;/em&#x3E; to not stomp on
existing files, and cloning to / will give you a &#x27;destination is not
empty&#x27; error by default.  This is a good thing, but we have to work
around it by cloning elsewhere, then moving the &#x3C;strong&#x3E;.hg&#x3C;/strong&#x3E; directory
manually to /. There&#x27;s no need to populate the resulting checkout
directory with the files, so we pass the &#x27;-U&#x27; flag to clone.&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;$ hg clone -U /tmp/example.bndl /tmp/confs
$ sudo mv /tmp/confs/.hg /
$ rm -rf /tmp/confs
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;The repository state now needs to be resynced before we can
use it, late binding the repository to the machine.  (Thanks
to &#x3C;a href=&#x22;http://www.deveiate.org/&#x22;&#x3E;Michael Granger&#x3C;/a&#x3E; for pointing
&#x3C;a href=&#x22;http://hgtip.com/tips/advanced/2010-04-23-debug-command-tricks/&#x22;&#x3E;this&#x3C;/a&#x3E;
out.) Since Mercurial will find the repo in /, you can run these
commands from anywhere on the system (that isn&#x27;t within another
Mercurial repo):&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;$ hg debugsetparent tip
$ hg debugrebuildstate
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;Finally, extract the files from the repo over the existing system files.&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;$ hg revert --all
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;Fwa-tow!  Okay, moving onwards.&#x3C;/p&#x3E;

&#x3C;h2&#x3E;Homedir files&#x3C;/h2&#x3E;

&#x3C;p&#x3E;With per-machine config repos, you very rarely have a need for
branching, or pulling changes from one place to another.  It&#x27;s possible,
of course, but I like to think of it as a bonus, instead of a regular
way to work with them.&#x3C;/p&#x3E;

&#x3C;p&#x3E;My homedir config, on the other hand, is used between no less than 6
different systems.  Different operating systems, different versions of
applications, and different environments.   I really don&#x27;t want separate
repositories for each permutation -- I want to check my homedir out and
get to work.&#x3C;/p&#x3E;

&#x3C;p&#x3E;The idea here is to have a foundation -- base configurations that are
identical between all workstations, and then layer on changes needed
for each workstation that can be tracked separately, but still carried
with the primary repository.  (This method works equally well for two
workstations or twenty.)&#x3C;/p&#x3E;

&#x3C;p&#x3E;Enter &#x3C;a href=&#x22;http://mercurial.selenic.com/wiki/MqExtension/&#x22;&#x3E;MQ&#x3C;/a&#x3E;.&#x3C;/p&#x3E;

&#x3C;p&#x3E;MQ has the concept of &#x22;guards&#x22; -- tags you can apply to individual
patches, that alter the default patch stack.  If you have a patch (or
patches) that change the base configurations for a workstation, you can
guard it with an arbitrary label, then select/set that label for the
workstations that it should be valid for.  Machine &#x22;A&#x22;&#x27;s configurations
are completely ignored when on machine &#x22;B&#x22;, and visa versa.&#x3C;/p&#x3E;

&#x3C;p&#x3E;I keep one primary repo that all machines with my homedir environment
sync from (and to.)  Initial setup looks like this -- very similar to
the machine repo setup, but with the addition of MQ:&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;$ hg init repo/homedir
$ hg init --mq repo/homedir
$ cd repo/homedir
$ echo &#x27;.*&#x27; &#x26;gt; .hgignore
$ hg add .hgignore
$ hg commit -m &#x22;Initial commit of homedir repository&#x22;
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;Before continuing, I recommend setting up a shell alias
for working with MQ, as mentioned in the
&#x3C;a href=&#x22;http://tortoisehg.bitbucket.org/hgbook/1.4/managing-change-with-mercurial-queues.html#id2858016&#x22;&#x3E;hgbook&#x3C;/a&#x3E;.&#x3C;/p&#x3E;

&#x3C;p&#x3E;For each workstation, perform the same initial trick as above with the
machine repos.  You only have to do perform this &#x27;bootstrapping&#x27; once
per system.  Note the use of &#x3C;em&#x3E;qclone&#x3C;/em&#x3E; instead of &#x3C;em&#x3E;clone&#x3C;/em&#x3E;, so we snag the
MQ patch repo too.&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;$ cd ~
$ hg qclone -U repo/homedir /tmp/homedir
$ mv /tmp/homedir/.hg .
$ rm -rf /tmp/homedir
$ hg debugsetparent tip
$ hg debugrebuildstate
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;Add your dotfiles and whatever else you want as part of your base
homedir foundation.&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;$ hg add .i3/*
$ hg add .bashrc .vimrc ...
$ ...
$ hg commit -m &#x27;Added some files for all environments&#x27;
$ hg push
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;Ok.  Now&#x27;s where it gets interesting.  Lets say you&#x27;re on a machine
called &#x22;hotsoup&#x22;, and you want specific configurations that ONLY apply
to it.  Create a new MQ patch file and guard!  You can call it whatever
you want, but I like to name both the patches and the guards after the
hostname they are supposed to apply to.&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;$ hg qnew hotsoup -m &#x27;Configs specific to hotsoup&#x27;
$ hg qpop
$ hg qguard hotsoup +hotsoup
$ mq commit -m &#x27;Initial commit of hotsoup patch&#x27;
$ mq push
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;Now that the patch is guarded, it won&#x27;t apply to any machine that
doesn&#x27;t have a matching &#x27;hotsoup&#x27; guard.   So on the real &#x27;hotsoup&#x27;
machine, select the guard.  You should see the following:&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;$ hg qselect hotsoup
number of guarded, applied patches has changed from 1 to 0
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;You only need to do this once, after the initial homedir repo
qcloning. Repeat the process on any number of machines.  One guard per
workstation, and each workstation will only &#x22;see&#x22; its specific patch.
If you want to commit new home directory files for all workstations,
just &#x3C;strong&#x3E;hg qpop&#x3C;/strong&#x3E; the machine patch and commit as normal.  Changes
while the patch is applied (&#x3C;strong&#x3E;hg qpush&#x3C;/strong&#x3E;) will be applied only to that
particular workstation.&#x3C;/p&#x3E;

&#x3C;p&#x3E;Pretty.  Dang.  Nice.&#x3C;/p&#x3E;

&#x3C;h2&#x3E;Gotchas?&#x3C;/h2&#x3E;

&#x3C;p&#x3E;Mercurial doesn&#x27;t track permissions, other than the executable bit.
If some of your tracked files require specific perms, you&#x27;ll need to
save them on checkin and reapply them on checkout.  There are lots of
tools to do this, depending on your operating system.  My preference is
&#x3C;a href=&#x22;http://people.freebsd.org/~kientzle/libarchive/man/mtree.5.txt&#x22;&#x3E;mtree&#x3C;/a&#x3E;
for FreeBSD.&#x3C;/p&#x3E;

&#x3C;p&#x3E;You can go a step further and add hooks to the checked out repository&#x27;s
.hgrc file, so retaining and reapplying permissions is automatic.  This
StackOverflow &#x3C;a href=&#x22;http://stackoverflow.com/questions/1289816/can-mercurial-be-made-to-preserve-file-permissions&#x22;&#x3E;question&#x3C;/a&#x3E;
outlines that method nicely!&#x3C;/p&#x3E;
</description>
</item>
<item rdf:about="http://www.martini.nu/blog/2010/06/tor-vbox.html">
<title>Serve an anonymous shell via Tor</title>
<link>http://www.martini.nu/blog/2010/06/tor-vbox.html</link>
<description>&#x3C;p&#x3E;I&#x27;ve been an avid user of &#x3C;a href=&#x22;http://www.torproject.org/&#x22;&#x3E;Tor&#x3C;/a&#x3E; since
about 2005.  Retaining the right of anonymity and individual
privacy grows increasingly important as different communication
technologies emerge and become ubiquitous, as the recent Facebook
&#x3C;a href=&#x22;http://www.eff.org/deeplinks/2010/04/facebook-timeline&#x22;&#x3E;heat&#x3C;/a&#x3E; has
reminded us.  If you don&#x27;t think it matters, you need to stop what
you&#x27;re doing right now and read Phil Zimmerman&#x27;s excellent PGP
&#x3C;a href=&#x22;http://www.philzimmermann.com/EN/essays/WhyIWrotePGP.html&#x22;&#x3E;justification&#x3C;/a&#x3E;.
(I am particularity fond of the postcard metaphor.)&#x3C;/p&#x3E;

&#x3C;p&#x3E;Done?  Okay.  Lets move on!&#x3C;/p&#x3E;

&#x3C;p&#x3E;While most people use Tor simply for anonymous web browsing, Tor also provides
a slick way to host a service (web site, IRC chat server, etc) called a &#x3C;a href=&#x22;http://www.torproject.org/hidden-services.html.en&#x22;&#x3E;Hidden
Service&#x3C;/a&#x3E;.  These services
are &#x22;hidden&#x22; because they are only accessible via the Tor network, and are
under the same anonymity umbrella as Tor clients -- unless they accidently
expose information about themselves, it is essentially impossible to determine
the source location of the service.&#x3C;/p&#x3E;

&#x3C;p&#x3E;As it turns out, not exposing information about yourself is a lot more
difficult than you might imagine; even for a single process.  Hosting a simple
web page involves configuring your server signature and potentially customizing
error messages.  Are you sure any images on that web page don&#x27;t have embedded
EXIF data?  What about documents that support author metadata (PDF, DOC, many
many many more?)  META tags if you used an HTML editor to construct your pages?&#x3C;/p&#x3E;

&#x3C;p&#x3E;This got me thinking about how to offer other services to anonymous users.
Wouldn&#x27;t an encrypted backup service be neat?  That wouldn&#x27;t really be
practical for a hobbyist (storage needs, Tor network speeds, etc) -- but a
generic anonymous shell would certainly be a nice communications tool.  You
could use it for file storage, chat, message passing, or even as a digital
&#x3C;a href=&#x22;http://en.wikipedia.org/wiki/Dead_drop&#x22;&#x3E;dead drop&#x3C;/a&#x3E;.  If I (or anyone) wanted
to offer that as a hidden service, how best to do so while 1) remaining
anonymous as a provider and 2) providing default settings that retain Tor
ideals (trusted privacy, resistance to traffic analysis, and accessibility for
blocked users) to the shell accounts?  We&#x27;re talking about exposing an entire
OS, after all.&#x3C;/p&#x3E;

&#x3C;p&#x3E;Here&#x27;s what I came up with.  Steel thyself for diagram madness!!&#x3C;/p&#x3E;

&#x3C;p&#x3E;&#x3C;a href=&#x22;/images/blog/2010/06/tor-vbox.png&#x22; class=&#x22;highslide&#x22; onclick=&#x22;return hs.expand(this)&#x22;&#x3E;
    &#x3C;img src=&#x22;/images/blog/2010/06/thumb_tor-vbox.png&#x22;
    alt=&#x22;Diagram-o-rama!&#x22;    /&#x3E;
&#x3C;/a&#x3E;&#x3C;/p&#x3E;

&#x3C;p&#x3E;There are a lot of advantages to this setup.  Entire environment
snapshot/rollback, complete machine mobility, FreeBSD &#x27;secure levels&#x27;
for added security, and network obfuscation via &#x3C;a href=&#x22;VirtualBox&#x22;&#x3E;VirtualBox&#x3C;/a&#x3E;
&#x3C;a href=&#x22;http://en.wikipedia.org/wiki/Network_address_translation&#x22;&#x3E;NAT&#x3C;/a&#x3E; and
OpenBSD&#x27;s &#x3C;a href=&#x22;http://openbsd.org/faq/pf/&#x22;&#x3E;PF&#x3C;/a&#x3E;.&#x3C;/p&#x3E;

&#x3C;p&#x3E;And the biggest disadvantage?  Speed.  Tor is designed for privacy, not
for performance.  It&#x27;s really, really slow.  I&#x27;m talking 2400 baud modem
slow, at times.  Again, this isn&#x27;t a deal breaker if you&#x27;ve got your
expectations set.  You can help the overall speed of the network, too.
More on this later.&#x3C;/p&#x3E;

&#x3C;p&#x3E;So, here&#x27;s a step-by-step for the setup I&#x27;m using.&#x3C;/p&#x3E;

&#x3C;h2&#x3E;Tor Setup&#x3C;/h2&#x3E;

&#x3C;p&#x3E;In your &#x3C;em&#x3E;torrc&#x3C;/em&#x3E; file, you can enable the hidden service via two lines of config.&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;HiddenServiceDir /path/to/service_dir/
HiddenServicePort 22 127.0.0.1:50022
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;This automatically creates two files wherever your &#x3C;em&#x3E;service_dir&#x3C;/em&#x3E; points
to; the unique *.onion hostname that your Tor client is now advertising
to relays, and the private key for it.  Don&#x27;t lose this key if you care
about hanging on to your *.onion hostname.&#x3C;/p&#x3E;

&#x3C;p&#x3E;The &#x3C;em&#x3E;HiddenServicePort&#x3C;/em&#x3E; directive tells Tor that incoming connections
to port &#x3C;em&#x3E;22&#x3C;/em&#x3E; (ssh) that are coming in via Tor should be redirected to
localhost, port &#x3C;em&#x3E;50022&#x3C;/em&#x3E;.  We&#x27;ll now tell VirtualBox to listen on that
port, and do its own forwarding.&#x3C;/p&#x3E;

&#x3C;h2&#x3E;VirtualBox Host&#x3C;/h2&#x3E;

&#x3C;p&#x3E;One of the biggest reasons to use VirtualBox for this server is
mobility.  As long as you carry the generated Tor hidden service key
alongside your VDI file, you can essentially move this server to any
VirtualBox supported host OS, anywhere in the world, and it&#x27;ll still be
accessible via Tor at the same &#x3C;em&#x3E;.onion&#x3C;/em&#x3E; hostname.&#x3C;/p&#x3E;

&#x3C;p&#x3E;It reminds me of the inter-dimensional Black Fortress from the old
movie &#x3C;a href=&#x22;http://en.wikipedia.org/wiki/Krull_(film)&#x22;&#x3E;Krull&#x3C;/a&#x3E;, or the &#x3C;a href=&#x22;http://en.wikipedia.org/wiki/The_Dark_Tower_(series)&#x22;&#x3E;Dark
Tower&#x3C;/a&#x3E; from
Stephen King&#x27;s Gunslinger series.  Some &#x22;physical&#x22; construct that
ethereally shifts locations.  Neat-o.  Let&#x27;s call it &#x22;Tower&#x22; for kicks.&#x3C;/p&#x3E;

&#x3C;p&#x3E;VirtualBox also gives us the ability to easily hide behind
NAT.  The guest operating system receives network information
from the host environment, providing an immediate sandbox,
and IANA private IP ranges.  (More on those specifics
&#x3C;a href=&#x22;http://www.virtualbox.org/manual/ch06.html#network_nat&#x22;&#x3E;here&#x3C;/a&#x3E;.)&#x3C;/p&#x3E;

&#x3C;p&#x3E;First off, lets forward traffic from port &#x3C;em&#x3E;50022&#x3C;/em&#x3E; to the virtual machine
at port &#x3C;em&#x3E;22&#x3C;/em&#x3E;, so the Tor network can eventually reach the ssh daemon.&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;% VBoxManage modifyvm &#x22;Tower&#x22; --natpf1 &#x22;ssh,tcp,,50022,,22&#x22;
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;Unfortunately, VirtualBox NAT exposes resolvers and search domains via
DHCP from the host environment by default, so we require some additional
guest configuration.&#x3C;/p&#x3E;

&#x3C;h2&#x3E;VirtualBox Guest (aka FreeBSD Host)&#x3C;/h2&#x3E;

&#x3C;p&#x3E;The VirtualBox guest OS runs a recent &#x3C;a href=&#x22;http://www.freebsd.org/&#x22;&#x3E;FreeBSD&#x3C;/a&#x3E; image,
in itself acting as a host for a jail underneath it.  The single largest
potential for identifying machine location is the internet itself.  The local
IP address will be 10.0.2.15 (by default), so that doesn&#x27;t give any location
sensitive info away... but what about a simple traceroute?  Any outbound
connection will reveal the server&#x27;s gateway IP, and it&#x27;s simply not feasible to
try and subvert this without &#x3C;a href=&#x22;https://trac.torproject.org/projects/tor/wiki/TheOnionRouter/TransparentProxy#BSDpf&#x22;&#x3E;forwarding all
traffic&#x3C;/a&#x3E;
back across Tor.&#x3C;/p&#x3E;

&#x3C;p&#x3E;So the first thing we do is block all outbound traffic via PF.  I
renamed the interface to &#x3C;em&#x3E;net0&#x3C;/em&#x3E; so we can reference it everywhere, and
if we decide to change the underlying virtual device, we only need do so
in one location.  Here&#x27;s an example &#x3C;em&#x3E;/etc/pf.conf&#x3C;/em&#x3E;.  We&#x27;re not running
ssh on this host, only on the jail inside of it -- so ssh traffic that
hits the host is redirected inside to &#x3C;em&#x3E;127.0.0.2&#x3C;/em&#x3E;.  We blindly accept
all other traffic -- this is safe as no traffic can reach this machine
that is not explicitly port forwarded from VirtualBox.&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;net_if=&#x22;net0&#x22;
set optimization normal
set block-policy return
set loginterface $net_if
set skip on lo0
scrub in on $net_if all fragment reassemble
rdr pass on $net_if proto tcp to port 22 -&#x26;gt; 127.0.0.2
block out on $net_if
pass in on $net_if
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;We should also override the dhclient options file at
&#x3C;em&#x3E;/etc/dhclient.conf&#x3C;/em&#x3E;, so host information remains private.&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;supersede domain-name &#x22;tower&#x22;;
supersede domain-name-servers 8.8.8.8;
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;Also -- resist the urge to set the timezone!  UTC time doesn&#x27;t give away what
part of the world you&#x27;re in.  Here&#x27;s the &#x3C;em&#x3E;/etc/rc.conf&#x3C;/em&#x3E; that loads up PF, and
starts up the jail.  (Check the jail(8) &#x3C;a href=&#x22;http://www.freebsd.org/cgi/man.cgi?query=jail&#x22;&#x3E;man
page&#x3C;/a&#x3E; if you are looking for
information on how to create a new one -- that&#x27;s outside the scope of this
already very long post.)&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;hostname=&#x22;tower-host&#x22;
ifconfig_le0_name=&#x22;net0&#x22;
ifconfig_net0=&#x22;DHCP&#x22;
pf_enable=&#x22;YES&#x22;
pf_rules=&#x22;/etc/pf.conf&#x22;
pflog_enable=&#x22;YES&#x22;
sendmail_enable=&#x22;NONE&#x22;
tmpmfs=&#x22;YES&#x22;
tmpsize=&#x22;128m&#x22;
fsck_y_enable=&#x22;YES&#x22;
kern_securelevel_enable=&#x22;YES&#x22;
kern_securelevel=&#x22;3&#x22;
jail_enable=&#x22;YES&#x22;
jail_list=&#x22;tower&#x22;
jail_set_hostname_allow=&#x22;NO&#x22;
jail_socket_unixiproute_only=&#x22;YES&#x22;
jail_sysvipc_allow=&#x22;YES&#x22;
jail_tower_rootdir=&#x22;/jails/tower&#x22;
jail_tower_hostname=&#x22;tower&#x22;
jail_tower_interface=&#x22;net0&#x22;
jail_tower_ip=&#x22;127.0.0.2&#x22;
jail_tower_exec_start=&#x22;/bin/sh /etc/rc&#x22;
jail_tower_exec_stop=&#x22;/bin/sh /etc/rc.shutdown&#x22;
jail_tower_devfs_enable=&#x22;YES&#x22;
jail_tower_fdescfs_enable=&#x22;NO&#x22;
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;What else?  We should ensure users can&#x27;t see what other users are doing
via &#x3C;em&#x3E;sysctl&#x3C;/em&#x3E; variables.  (These behaviors are carried to the jail.)
Also, I set a cron that removes login histories every minute.&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;% cat /etc/sysctl.conf
security.bsd.see_other_uids=0
security.bsd.see_other_gids=0
security.bsd.unprivileged_read_msgbuf=0

% echo &#x27;* * * * * root rm /var/log/wtmp \ 
    /jails/tower/var/log/wtmp&#x27; &#x26;gt;&#x26;gt; /etc/crontab
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;After all of this stuff is set up to our content, lets lock it down via
&#x3C;em&#x3E;chflags&#x3C;/em&#x3E;.&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;% chflags schg /etc/pf.conf /etc/rc.conf \ 
    /etc/dhclient.conf /etc/sysctl.conf /etc/crontab
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;Doing this, in combination with &#x3C;em&#x3E;securelevel&#x3C;/em&#x3E;, will protect the files
from modification.  Even if an attacker somehow gains root access in
this FreeBSD host, they can&#x27;t disable the firewall or change these
files without rebooting to single user mode -- and there&#x27;s no network
in single user mode.  This also means: if you want to make changes, you
need to be sitting at the VirtualBox console.&#x3C;/p&#x3E;

&#x3C;h2&#x3E;FreeBSD Jail&#x3C;/h2&#x3E;

&#x3C;p&#x3E;This is finally the environment that an anonymous Tor user will be
exposed to.  Why the additional layer here?  Couldn&#x27;t you just have
people log in to the FreeBSD host?&#x3C;/p&#x3E;

&#x3C;p&#x3E;Well, sure.  However, good hardening practices include the assumption
that the box &#x3C;em&#x3E;can&#x3C;/em&#x3E; be compromised (if not already so), and configure
it as such -- just like we assumed someone having root in the host
(and chflag&#x27;ed accordingly.)  The chances of &#x22;leaking&#x22; identifying
information are greater from the guest OS to VirtualBox than they are
from a jail to the host that is properly locked down.  In addition, it
adds an extra obfuscation layer that an attacker would have to break
through.  Root access in a jail is fairly useless.  They can&#x27;t make any
permanent system modifications, nor read any additional system data
that a normal user couldn&#x27;t.  They can&#x27;t even see the current firewall
ruleset.  They &#x3C;em&#x3E;can&#x3C;/em&#x3E; read other user&#x27;s homedir data -- but just like the
real operator of this service, an attacker would have no information
available to determine identity.&#x3C;/p&#x3E;

&#x3C;p&#x3E;Some other things to set up:&#x3C;/p&#x3E;

&#x3C;ul&#x3E;
&#x3C;li&#x3E;Bump up the &#x3C;em&#x3E;LoginGraceTime&#x3C;/em&#x3E; in the sshd config, since Tor is slow.&#x3C;/li&#x3E;
&#x3C;li&#x3E;Add automatic shell history removal to /etc/csh.logout and /etc/profile, depending on if the default shell is tcsh or bash, respectively.&#x3C;/li&#x3E;
&#x3C;li&#x3E;Add a reasonable hostname to &#x3C;em&#x3E;/etc/hosts&#x3C;/em&#x3E; for &#x3C;em&#x3E;127.0.0.2&#x3C;/em&#x3E;.&#x3C;/li&#x3E;
&#x3C;li&#x3E;Disable adjkerntz in /etc/crontab -- time is set from the host.&#x3C;/li&#x3E;
&#x3C;li&#x3E;Maybe precreate a bunch of users?  If you&#x27;re invited to a shell server by a pal, and there is only one other account... that would be an identity leak.  ;)&#x3C;/li&#x3E;
&#x3C;li&#x3E;Install any additional ports/packages you want to offer from the shell.  I like ntalk/ytalk!&#x3C;/li&#x3E;
&#x3C;li&#x3E;How about a quick script for creating new accounts?  Maybe linked to a &#x3C;em&#x3E;guest&#x3C;/em&#x3E; account for anonymous creations?&#x3C;/li&#x3E;
&#x3C;/ul&#x3E;

&#x3C;p&#x3E;Here&#x27;s the entirety of the system &#x3C;em&#x3E;rc.conf&#x3C;/em&#x3E; for the jail:&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;sshd_enable=&#x22;YES&#x22;
inetd_enable=&#x22;YES&#x22;
syslogd_enable=&#x22;NO&#x22;
cron_enable=&#x22;NO&#x22;
update_motd=&#x22;NO&#x22;
sendmail_enable=&#x22;NONE&#x22;
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;And here is what you&#x27;d see if others are logged in.  Note that the
remote IP will appear to be the VirtualBox host.&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E; 3:51PM  up 14:53, 1 user, load averages: 0.03, 0.01, 0.00
USER             TTY      FROM              LOGIN@  IDLE WHAT
q44r4            pts/0    10.0.2.2          3:51PM     - w
achgung          pts/2    10.0.2.2          2:21AM     - -
lenny            pts/1    10.0.2.2         10:51AM     - -
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;h2&#x3E;The Easy Way&#x3C;/h2&#x3E;

&#x3C;p&#x3E;Instead of re-doing all of that above, you could also just grab my
VirtualBox machine that already includes all of it.  Fire
it up, login as guest, enjoy.  The host password is &#x3C;em&#x3E;root/root&#x3C;/em&#x3E;, if you
wanted to change it.&#x3C;/p&#x3E;

&#x3C;p&#x3E;Get it &#x3C;a href=&#x22;http://dl.dropbox.com/u/7234177/Tower.zip&#x22;&#x3E;here&#x3C;/a&#x3E; -- it&#x27;s about
325M, and should import right into VirtualBox.&#x3C;/p&#x3E;

&#x3C;h2&#x3E;Configuring your SSH client&#x3C;/h2&#x3E;

&#x3C;p&#x3E;SSH needs to be told to use Tor for connectivity, and for DNS lookups (so it
knows how to find a .onion addresses.)
The &#x3C;a href=&#x22;http://bent.latency.net/bent/git/goto-san-connect-1.85/src/connect.html&#x22;&#x3E;connect&#x3C;/a&#x3E;
proxy forwarder can do this really easily.  It&#x27;s available in macports, FreeBSD
ports, and Ubuntu&#x27;s package management.  You can also compile it yourself, it
doesn&#x27;t have any funky dependencies.&#x3C;/p&#x3E;

&#x3C;p&#x3E;After it&#x27;s installed, add this configuration chunk into your &#x3C;em&#x3E;~/.ssh/config&#x3C;/em&#x3E; file:&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;Host *.onion
    PubKeyAuthentication no
    VisualHostKey yes
    Compression yes
    ForwardAgent no
    ForwardX11 no
    PreferredAuthentications password
    ProxyCommand /path/to/connect -S 127.0.0.1:9050 %h %p
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;... and that&#x27;s it.  You&#x27;ll be able to ssh as normal, and if you&#x27;re
connected to Tor, ssh will know what to do with hosts that end in
.onion.  Make sure that if you&#x27;re connecting to a .onion host, that you
explicitly pass your username -- otherwise, ssh defaults to using the
username of the currently logged in user.&#x3C;/p&#x3E;

&#x3C;h2&#x3E;What else?&#x3C;/h2&#x3E;

&#x3C;p&#x3E;If you have even a little bit of bandwidth to spare, please consider being a
Tor &#x3C;a href=&#x22;http://www.torproject.org/docs/tor-doc-relay.html.en&#x22;&#x3E;relay&#x3C;/a&#x3E;.  It can
&#x3C;a href=&#x22;https://trac.torproject.org/projects/tor/wiki/TheOnionRouter/TorFAQ#DoIgetbetteranonymityifIrunarelay&#x22;&#x3E;arguably&#x3C;/a&#x3E;
increase your own privacy while using Tor, and it improves the overall speed of
the Tor network.  It&#x27;s easy to limit what kind of traffic you&#x27;ll allow your
relay to pass, and you can even bandwidth limit it.&#x3C;/p&#x3E;

&#x3C;p&#x3E;Have I forgotten anything?  Could privacy be improved in this
environment for end users and/or the server operator?  Let me know --
I&#x27;ll update the VirtualBox export!&#x3C;/p&#x3E;

&#x3C;p&#x3E;How would you go about doing this?&#x3C;/p&#x3E;
</description>
</item>
<item rdf:about="http://www.martini.nu/blog/2010/05/rest-doing-it-wrong.html">
<title>Publishing a REST API?</title>
<link>http://www.martini.nu/blog/2010/05/rest-doing-it-wrong.html</link>
<description>&#x3C;p&#x3E;Aww, &#x3C;a href=&#x22;http://www.facebook.com/&#x22;&#x3E;Facebook&#x3C;/a&#x3E;.  We all know your backend is a
&#x3C;a href=&#x22;http://www.makeuseof.com/tag/facebook-work-nuts-bolts-technology-explained/&#x22;&#x3E;Frankenstein&#x3C;/a&#x3E;
of legacy foundation overlaid with new-and-cool features that could probably
make the&#x3C;/p&#x3E;

&#x3C;p&#x3E;&#x3C;a href=&#x22;http://www.livejournal.com/&#x22;&#x3E;LiveJournal&#x3C;/a&#x3E; codebase actually appear
organized.  In day to day usage of your service, it doesn&#x27;t really matter.
Somehow it is all glued together into a cohesive experience for the end user,
and I rarely notice the .php extension in the address bar.  And your user
interface team remains &#x3C;em&#x3E;so very good&#x3C;/em&#x3E;. (I mean that.)  It shows, however, when
a developer cracks the hood of your
&#x3C;a href=&#x22;http://en.wikipedia.org/wiki/Representational_State_Transfer&#x22;&#x3E;REST&#x3C;/a&#x3E; API.  So,
so ghetto.&#x3C;/p&#x3E;

&#x3C;p&#x3E;And you&#x27;re not alone.  I&#x27;m noticing a disturbing trend with API designers.  I&#x27;m
looking at you, &#x3C;a href=&#x22;http://www.twitter.com/&#x22;&#x3E;Twitter&#x3C;/a&#x3E;.  Don&#x27;t think you&#x27;re getting
away with it either, &#x3C;a href=&#x22;http://www.foursquare.com/&#x22;&#x3E;Foursquare&#x3C;/a&#x3E;.  You guys are
the cool kids.  You shouldn&#x27;t have a bunch of cruft lying around.  You still
can fix this, and &#x3C;em&#x3E;your&#x3C;/em&#x3E; developer userbase would actually appreciate you for
it.&#x3C;/p&#x3E;

&#x3C;p&#x3E;Here&#x27;s the gist: REST is designed to piggyback on HTTP, and HTTP is
surprisingly full featured.  You get an amazing array of features available to
you as part of the protocol, like document caching via last-modified times,
byte-range fetches, pipelining requests, a huge assortment of authentication
options, and content negotiation.  You can pick and choose what you want to
support, and HTTP provides for a standard way to accomplish it. HTTP
&#x3C;em&#x3E;compliments&#x3C;/em&#x3E; the REST design philosophy, and if you&#x27;re creating a REST API
that doesn&#x27;t take advantage of that fact (or worse, re-invents portions of it),
then you just look either lazy, or like you never read any HTTP RFCs.&#x3C;/p&#x3E;

&#x3C;h2&#x3E;HTTP verbs&#x3C;/h2&#x3E;

&#x3C;p&#x3E;A verb is a synonym for an HTTP method.  Given a URI, what is your intent?
Reading it?  Adding new content to it?  Removing it altogether?&#x3C;/p&#x3E;

&#x3C;p&#x3E;HTTP has a lot of verbs.  But for purposes of REST, it&#x27;s pretty
straightforward.  We&#x27;ll just use 4 of them, which should cover 95% of the REST
use case:&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;GET     Read from a resource
POST    Create a new resource
PUT     Update an existing resource
DELETE  Remove a resource
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;Foursquare gets this largely right (GET a list of &#x3C;em&#x3E;checkins&#x3C;/em&#x3E; vs POST a
&#x3C;em&#x3E;checkin&#x3C;/em&#x3E;), as does Twitter.  Both strangely omit the PUT verb completely
though, using POST for all writes -- regardless of whether the write is
creating new content or updating existing stuff.  Even Wikipedia confuses what
PUT should do, but the HTTP &#x3C;a href=&#x22;http://www.ietf.org/rfc/rfc2616.txt&#x22;&#x3E;RFC&#x3C;/a&#x3E; is
clearer.  PUT is for updates!&#x3C;/p&#x3E;

&#x3C;p&#x3E;There is even a handy dandy error code dedicated to HTTP method handling.  As
an example, if you try and POST/PUT to a resource that should always be read
only, your server should respond with a &#x3C;strong&#x3E;405 Method not allowed&#x3C;/strong&#x3E;, along with
an &#x3C;strong&#x3E;Allow&#x3C;/strong&#x3E; header that lists the verbs you &#x3C;em&#x3E;can&#x3C;/em&#x3E; use at that URI.  See?  HTTP
takes care of you like a gentle lover, and any decent HTTP client (web,
desktop, or whatever) should handle your API in the correct fashion.&#x3C;/p&#x3E;

&#x3C;p&#x3E;With the exception of adding video, Facebook&#x27;s API completely ignores the
concept of verbs.  Everything is a GET request, and the verb is embedded into
the resource.  &#x3C;em&#x3E;getSomething&#x3C;/em&#x3E;.  &#x3C;em&#x3E;addSomethingElse&#x3C;/em&#x3E;.  At that point, you&#x27;re
immediately not using REST.  You&#x27;re just publishing a loose collection of
random URIs and calling it an API.  You might as well be using
&#x3C;a href=&#x22;http://en.wikipedia.org/wiki/SOAP&#x22;&#x3E;SOAP&#x3C;/a&#x3E;, because that&#x27;s what you just
reinvented, without all the XML suck.  Oh, wait... that brings me to&#x3C;/p&#x3E;

&#x3C;h2&#x3E;content negotiation&#x3C;/h2&#x3E;

&#x3C;p&#x3E;Everyone is getting this wrong.  Here&#x27;s the litmus test -- if you need to embed
your desired response format in the resource URI, the API is being &#x3C;em&#x3E;lazy&#x3C;/em&#x3E;.&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;https://api.facebook.com/method/users.getInfo?uids=4&#x26;amp;format=JSON
http://api.foursquare.com/v1/user.json
http://api.twitter.com/1/statuses/update.json
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;Again, HTTP supplies a standard method to do this.  A client can send an
&#x3C;em&#x3E;Accept&#x3C;/em&#x3E; header, that can even specify order of preference it can deal with the
data.  All format types are MIME.  Realistically, most clients will have such a
strong preference for a specific serialization format, that they won&#x27;t ever use
Accept parameters or qvalue weights.  They&#x27;ll just say &#x22;gimme the resource in
application/json format!&#x22; and the server will say SURE.  Alternatively, the
client requests a format that the server can&#x27;t comply with, and lo and behold
-- there&#x27;s an error status for that, too -- &#x3C;strong&#x3E;406 Not Acceptable&#x3C;/strong&#x3E;.  Servers,
if they want to be -really- nice, can provide alternate resource URIs in the
body of the error that explain to the client what to do instead, in the
originally requested format!&#x3C;/p&#x3E;

&#x3C;p&#x3E;If the APIs actually used this handy header, then they could rapidly start
supporting things like compressed JSON streams, or new serialization formats on
the fly, all while continuing to support the other client applications out
there that don&#x27;t support the new and fancy formats.  This opens up the API to a
whole audience of clients that might normally not be interested, while keeping
your resource URIs completely unchanged and static.&#x3C;/p&#x3E;

&#x3C;p&#x3E;Facebook&#x27;s new Graph API gets around the whole mess of serialization formats by
only supporting JSON.  Ever.  Want something else?  Working with a language
with subpar or no native JSON support?  Too bad.  I personally really like
JSON, but why would you intentionally cut off other formats when it would be
&#x3C;em&#x3E;so easy&#x3C;/em&#x3E; to support?&#x3C;/p&#x3E;

&#x3C;h2&#x3E;POST (kinda)&#x3C;/h2&#x3E;

&#x3C;p&#x3E;I update a &#x3C;a href=&#x22;http://en.wikipedia.org/wiki/Finger_protocol&#x22;&#x3E;plan&#x3C;/a&#x3E; file regularly,
and script updates in my plan file to Twitter.  (Then a FaceBook application
syncs from Twitter.)  This way, I can continue using my &#x22;update the world
before social networking existed&#x22; technology, while still telling Mom what&#x27;s up
on FaceBook.  That&#x27;s right.  Get off my lawn!!&#x3C;/p&#x3E;

&#x3C;p&#x3E;I like calling Twitter updates &#x27;twits&#x27;.  Twits + plan file?  Plits!  A CLIENT
IS BORN.  Here&#x27;s what a status update URI looks like to Twitter.&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;http://twitter.com/statuses/update.json?status=I%20eat%20burritos&#x26;amp;source=plit
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;Ok, what the hell is this lame excuse at REST?  Why do I have to include my
&#x27;source&#x27; in the URI, when there is a perfectly good User-Agent header?  Why on
earth must I embed the &#x3C;em&#x3E;content&#x3C;/em&#x3E; of the POST (thank you, it IS at least a POST)
in the URI after encoding it appropriately?  This is HTTP dammit! It has a very
solid concept of a content body!&#x3C;/p&#x3E;

&#x3C;p&#x3E;Just look at how pretty this would be if REST ideals were actually applied.&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;POST /statuses/update HTTP/1.0
Accept: application/json
User-Agent: plit
Content-Type: text/plain
Content-Length: 13

I eat burritos
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;What if someday, Twitter suddenly supports posting audio updates to your feed?
Like a giant social-networking Nextel walkie talkie!  (Please, for the love of
all that is holy, lets hope this never happens.)  Watch the magic.&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;POST /statuses/update HTTP/1.0
Accept: application/json
User-Agent: plit
Content-Type: audio/x-wav
Content-Length: 273

[audio stream here]
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;Notice that the API is essentially unchanged!  Twitter could simply
reply with what formats it can support, and the client can do the brainy
work of converting the audio to a supported format.  How would this ever
work with putting content in the URI?&#x3C;/p&#x3E;

&#x3C;p&#x3E;Much better dev experience, and less work for developers making clients
for your services.  A clear path for you, the service publisher, to
optionally provide all sorts of rich media options, while supporting
protocol standards between clients.&#x3C;/p&#x3E;

&#x3C;p&#x3E;DARE I SAY A BETTER WORLD.&#x3C;/p&#x3E;

&#x3C;p&#x3E;Please guys, lets take advantage of HTTP if you continue using it as a
transport.  Or if you stay the course, stop calling what you have REST.  It&#x27;s
misleading and just plain... not.&#x3C;/p&#x3E;
</description>
</item>
<item rdf:about="http://www.martini.nu/blog/2010/05/scp-petpeeves.html">
<title>A modest attempt to de-dumb scp</title>
<link>http://www.martini.nu/blog/2010/05/scp-petpeeves.html</link>
<description>&#x3C;p&#x3E;The title of this post isn&#x27;t entirely fair; scp is an &#x3C;em&#x3E;awesome&#x3C;/em&#x3E; utility,
and is probably one of my top 10 typed commands in a given day. (Sadly
true, I shuffle files around &#x3C;strong&#x3E;a lot&#x3C;/strong&#x3E;). Because of how often I use it,
however, I do have some long standing issues that have always striked me
as just plain silly behavior.&#x3C;/p&#x3E;

&#x3C;h2&#x3E;flag consistency&#x3C;/h2&#x3E;

&#x3C;p&#x3E;&#x3C;em&#x3E;scp&#x3C;/em&#x3E; strives to be consistent with its insecure predecessor, &#x3C;em&#x3E;rcp&#x3C;/em&#x3E;,
just like &#x3C;em&#x3E;ssh&#x3C;/em&#x3E; shares many of the same flags as &#x3C;em&#x3E;rsh&#x3C;/em&#x3E;. &#x3C;em&#x3E;rcp&#x3C;/em&#x3E; has been
around since 1982, and was largely obsoleted when &#x3C;em&#x3E;ssh&#x3C;/em&#x3E; and friends
became available in 1995.  Trying to share flags with the original
program you&#x27;re replacing is a noble idea.  Unfortunately, there is a
single flag that is in conflict between &#x3C;em&#x3E;ssh&#x3C;/em&#x3E; and &#x3C;em&#x3E;rcp&#x3C;/em&#x3E; -- -p.&#x3C;/p&#x3E;

&#x3C;p&#x3E;Because &#x3C;em&#x3E;scp&#x3C;/em&#x3E; uses all the same connection rules (user, password,
keypair) as &#x3C;em&#x3E;ssh&#x3C;/em&#x3E;, I think it makes more sense to be consistent with
&#x3C;em&#x3E;ssh&#x3C;/em&#x3E; -- not &#x3C;em&#x3E;rcp&#x3C;/em&#x3E;, which as of this writing, has been obsoleted for 15
years.  As an end user, I shouldn&#x27;t have to remember that &#x3C;em&#x3E;ssh&#x3C;/em&#x3E; needs a
-p to set a remote port, and &#x3C;em&#x3E;scp&#x3C;/em&#x3E; needs a -P.  Since &#x3C;em&#x3E;ssh&#x3C;/em&#x3E; doesn&#x27;t
actually use -P for anything, that&#x27;s where the original &#x3C;em&#x3E;rcp&#x3C;/em&#x3E; &#x22;preserve
modes&#x22; should land.&#x3C;/p&#x3E;

&#x3C;h2&#x3E;copying local files&#x3C;/h2&#x3E;

&#x3C;p&#x3E;&#x3C;em&#x3E;scp&#x3C;/em&#x3E; is for copying files across a network.  I don&#x27;t want it to ever
make local copies.  If I want a local copy, I&#x27;ll use &#x3C;em&#x3E;cp&#x3C;/em&#x3E;, thank you
very much.  How many times have you accidentally omitted the trailing
colon on a remote destination, just to end up with a user+host named
local copy?&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;$ touch testfile
$ scp testfile mahlon@martini.nu
$ ls -l mahlon\@martini.nu
-rw-r--r--  1 mahlon  users  0 May 12 07:33 mahlon@martini.nu
$ rm mahlon\@martini.nu
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;When would you -ever- want that behavior, and want to use &#x3C;em&#x3E;scp&#x3C;/em&#x3E; to do
it?  Never, I say!  Here&#x27;s what I think is an improvement:&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;$ touch testfile
$ scp testfile mahlon@martini.nu
Cowardly refusing to make a local copy of &#x27;testfile&#x27;.
$ ^D
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;h2&#x3E;local files validity&#x3C;/h2&#x3E;

&#x3C;p&#x3E;Another one when copying local files to remote destinations.  &#x3C;em&#x3E;scp&#x3C;/em&#x3E;
currently goes through all the work of connecting to the remote host
before bothering to check if the local file you&#x27;re trying to copy even
is available.&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;$ scp -v doesnt_exist mahlon@martini.nu:
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: Connecting to martini.nu [] port 22.
debug1: Connection established.
debug1: [...]
debug1: Found key in /home/mahlon/.ssh/known_hosts:5
debug1: Authentications that can continue: publickey,keyboard-interactive
debug1: Next authentication method: publickey
debug1: Offering public key: /home/mahlon/.ssh/id_dsa
debug1: Server accepts key: pkalg ssh-dss blen 433
debug1: Authentication succeeded (publickey).
debug1: channel 0: new [client-session]
debug1: Entering interactive session.
debug1: Sending command: scp -v -t .
doesnt_exist: No such file or directory
debug1: Transferred: stdin 0, stdout 0, stderr 0 bytes in 0.0 seconds
debug1: Bytes per second: stdin 0.0, stdout 0.0, stderr 0.0
debug1: Exit status 1
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;Why bother?  &#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;$ scp -v doesnt_exist mahlon@martini.nu:
doesnt_exist: No such file or directory
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;Rather than helplessly complain about this stuff into the internet
abyss, I went ahead and made a quick patch.  You get get it
&#x3C;a href=&#x22;http://www.martini.nu/misc/scp.patch&#x22;&#x3E;here&#x3C;/a&#x3E;, if you&#x27;re so inclined.&#x3C;/p&#x3E;
</description>
</item>
<item rdf:about="http://www.martini.nu/blog/2010/01/freebsd-pxe-grub.html">
<title>FreeBSD 8 PXEBoot with Grub2</title>
<link>http://www.martini.nu/blog/2010/01/freebsd-pxe-grub.html</link>
<description>&#x3C;p&#x3E;I just spent much longer on this than I care to admit.  Hopefully this
post will save someone else the time, until the dudes working on the
&#x3C;a href=&#x22;http://www.gnu.org/software/grub/grub-2.en.html&#x22;&#x3E;grub2&#x3C;/a&#x3E; project fill
their documentation out.&#x3C;/p&#x3E;

&#x3C;p&#x3E;Trying to PXEboot a recent FreeBSD environment using grub2pxe?  All the
docs out there for PXE+FreeBSD from early 2000 (or worse) and using
BSD&#x27;s &#x27;pxeboot&#x27; binary?  Can&#x27;t find &#x3C;em&#x3E;anything&#x3C;/em&#x3E; on the &#x27;kfreebsd&#x27; magic
of grub2?&#x3C;/p&#x3E;

&#x3C;p&#x3E;Here&#x27;s the magic sauce.  Note that I compressed the kernel, so it&#x27;ll
be much faster under tftp.&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;menuentry &#x22;FreeBSD 8.0 x86&#x22; {
   echo &#x22;Fetching the kernel and UFS root.&#x22;
   echo &#x22;This could take a few minutes, so hang tight... &#x22;

   kfreebsd /freebsd/x86_8.0/kernel/kernel.gz Dh
   kfreebsd_loadenv /freebsd/x86_8.0/device.hints
   kfreebsd_module /freebsd/x86_8.0/mfsroot.gz type=mfs_root
   set kFreeBSD.vfs.root.mountfrom=ufs:/dev/md0c

   echo &#x22;Aaaiiight!&#x22;
   sleep 2
}
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;So far, so good.&#x3C;/p&#x3E;
</description>
</item>
<item rdf:about="http://www.martini.nu/blog/2009/08/gadget.html">
<title>Reality check</title>
<link>http://www.martini.nu/blog/2009/08/gadget.html</link>
<description>&#x3C;p&#x3E;As I&#x27;m sitting here listening to a co-worker complain about how much his
new phone &#x22;sucks&#x22; compared to his old one, and remembering the stream of
issues he had with that one at the time, it slowly dawns on me how
&#x3C;em&#x3E;radically&#x3C;/em&#x3E; we&#x27;ve lost our sense of perspective.&#x3C;/p&#x3E;

&#x3C;p&#x3E;You&#x27;ve got a device that talks to satellites &#x3C;em&#x3E;in space&#x3C;/em&#x3E;.  It can talk
to your computer network.  You can communicate either via voice or text
with anyone in the world, without wires.  You can access the entirety
of human knowledge (or at least what made it to the Internet) from your
pocket.  Take pictures.  Videos.  Share them with your family.  Schedule
meetings.  Get directions, traffic status, and transit times from where
you are standing to &#x3C;em&#x3E;anywhere&#x3C;/em&#x3E;.  Listen to a large pile of high quality
music.  Shop.  Play video games.  Track packages.  Order movies to
your house.  Detect and tell you what constellation you&#x27;re looking at
(really.)  It even (gasp) has an address book.  The craziest thing
though?  The entire thing cost you &#x3C;em&#x3E;about 200 dollars&#x3C;/em&#x3E;.&#x3C;/p&#x3E;

&#x3C;p&#x3E;This sort of miracle device was nonexistent 5 short years ago, and
frankly, it is &#x3C;strong&#x3E;FUCKING MAGICAL&#x3C;/strong&#x3E;.&#x3C;/p&#x3E;

&#x3C;p&#x3E;Have we always been like this?  Or is it just as technology keeps
improving by leaps and bounds our expectations rise in step?  Did our
sense of entitlement suddenly just skyrocket past what vendors can
deliver in a pocket sized widget?&#x3C;/p&#x3E;

&#x3C;p&#x3E;If it doesn&#x27;t respond instantaneously every time you swipe a finger
across the screen, don&#x27;t complain.  Instead, take a moment and remember
what age you&#x27;re living in.  We didn&#x27;t have light bulbs 130 years ago.
How is it that you can be so lucky?!&#x3C;/p&#x3E;

&#x3C;p&#x3E;Now &#x3C;em&#x3E;shut up&#x3C;/em&#x3E;.&#x3C;/p&#x3E;
</description>
</item>
<item rdf:about="http://www.martini.nu/blog/2009/08/bootlegger.html">
<title>I must just have a bootleggy face</title>
<link>http://www.martini.nu/blog/2009/08/bootlegger.html</link>
<description>&#x3C;p&#x3E;Nadine and I trade each other a night a week for doing whatever.  She
usually uses it for getting her craft on, or having a cocktail with a
pal.  I use it to load up on happy hour margaritas and a movie with
&#x3C;a href=&#x22;http://www.deveiate.org/&#x22;&#x3E;Michael&#x3C;/a&#x3E;.  We&#x27;ve been going to the same
theater every week for about a year and a half now, usually directly
from work.  Unless there is nothing left to select from, we usually go
even if there isn&#x27;t a movie we&#x27;re aching to see -- it&#x27;s just fun to go
to a nice theater, and ripping apart a bad movie can sometimes be as
enjoyable as watching a good one.&#x3C;/p&#x3E;

&#x3C;p&#x3E;We&#x27;re programmers for &#x3C;a href=&#x22;http://www.laika.com/&#x22;&#x3E;LAIKA&#x3C;/a&#x3E;, and as such, we
carry around company laptops.  Going to a movie from work means we&#x27;ll
have laptop bags with us.  Stressing this point: &#x3C;em&#x3E;these aren&#x27;t our
laptops&#x3C;/em&#x3E;.  They belong to LAIKA, and they contain keys into the internal
network, along with various bits of intellectual property and privileged
data.&#x3C;/p&#x3E;

&#x3C;p&#x3E;So if I go to the theater, and as I walk in I&#x27;m quietly pulled aside and
asked to turn my bag in to a 16 year old minimum wage theater worker for
&#x22;safe keeping&#x22;, my answer will be an emphatic &#x3C;em&#x3E;no&#x3C;/em&#x3E;.&#x3C;/p&#x3E;

&#x3C;p&#x3E;My answer earned us a conversation with the
&#x3C;a href=&#x22;http://www.regmovies.com/&#x22;&#x3E;Regal&#x3C;/a&#x3E; manager on duty last week, who
hard-lined us for a solid 5 minutes before ultimately relenting, and
offering us some comment cards to air our grievances.  More likely
than not, they&#x27;ll be filtered into the trash can.  She also apparently
placed us on some sort of Regal movies terrorist list, which we realized
this week as we returned to the theater (laptops in tow), and were
&#x27;identified&#x27; immediately after our ticket purchase.&#x3C;/p&#x3E;

&#x3C;p&#x3E;We were asked to stop for a chat with the &#x3C;a href=&#x22;http://www.bridgeport-village.com/movies.html&#x22;&#x3E;BridgePort
Regal&#x3C;/a&#x3E; General Manager.
As we calmly refuted each assertion she made regarding Regal&#x27;s
&#x3C;a href=&#x22;http://www.regmovies.com/admittance-procedures.aspx&#x22;&#x3E;policy&#x3C;/a&#x3E;, she
too relented and let us into our movie.  She quickly assumed a tactic
of &#x22;it&#x27;s not MY policy, I&#x27;m just doing what I&#x27;m told&#x22;, which we were
sympathetic to.  I don&#x27;t want to give the false impression that we hold
any sway because we work at a movie studio, but I suggested that we
could open a dialog with Regal corporate to help adjust their policy
moving forward.  &#x3C;a href=&#x22;http://coraline.com/&#x22;&#x3E;Coraline&#x3C;/a&#x3E; was pirated too, after
all.&#x3C;/p&#x3E;

&#x3C;p&#x3E;Of course, Coraline wasn&#x27;t leaked from a theater at all, but rather the
DVD distributor.  Presumably, that&#x27;s because of all the hard work the
theaters are doing to prevent bootlegging.&#x3C;/p&#x3E;

&#x3C;p&#x3E;I&#x27;ll save you the mundane play-by-play of our conversation, but here are
the highlights.&#x3C;/p&#x3E;

&#x3C;ul&#x3E;
&#x3C;li&#x3E;&#x22;We don&#x27;t allow bags into the theater.&#x22;  (As two women walked by us
with purses.)&#x3C;/li&#x3E;
&#x3C;li&#x3E;&#x22;Well, it&#x27;s not bags per se, but electronic devices.&#x22; (As someone across
the hall is talking loudly on his cell.)&#x3C;/li&#x3E;
&#x3C;li&#x3E;&#x22;Can you leave your bags at home?&#x22;  (We go straight from work, and
it would be a 35 mile trip for Michael to attend their theater if he
went home first.)&#x3C;/li&#x3E;
&#x3C;li&#x3E;&#x22;Can you leave your bags in the car?&#x22; (Can you guarantee they&#x27;ll be
there when we return?  Of course not.  Not to mention the laptop is
worth -more- than my car.)&#x3C;/li&#x3E;
&#x3C;/ul&#x3E;

&#x3C;p&#x3E;I&#x27;m not blaming Kim (the General Manager) personally.  She was, after
all, just doing what she was told.  Though she didn&#x27;t give us a direct
contact to have this conversation with for Regal corporate, she seemed
a reasonable person.  So what&#x27;s a reasonable compromise here?  We&#x27;ve
spent a good deal of money on tickets in the last year and a half, and
I don&#x27;t want to feel discriminated against because I have what appears
to be a laptop.  I also don&#x27;t want to stop going to the movies after
work.  How can we avoid having this conversation every week?  How can
Regal feel they are doing their part to stop movie piracy and not giving
us &#x3C;em&#x3E;special&#x3C;/em&#x3E; treatment, while we&#x27;re simultaneously not punished for
being a loyal patrons that happen to own some technology?&#x3C;/p&#x3E;

&#x3C;p&#x3E;Short term?  Take any one of your workers.  Let&#x27;s be generous and say
they make $10/hr.  Have them come into the theater during the movie, and
&#x3C;strong&#x3E;see&#x3C;/strong&#x3E; if anyone is bootlegging!  If you see me with my laptop open
during the film, turned away from me, illuminating the chairs in front
of me... oh man, yeah.  Kick me the hell out.  Ban me.  Call the police.
Even better because you&#x27;ve made an example out of someone for other
would-be-bootleggers.  You have 18 theaters, so worst case scenario when
all of them are showing movies -- if it takes 3 minutes to do a sweep
per theater -- will cost you about $9 for a full check.  I&#x27;m fairly
certain that will be significantly cheaper than confiscating all bags
and/or electronic equipment that flow through your doors.  You aren&#x27;t a
coat check, you aren&#x27;t handing out ID tags for which device belongs to
which person... because that&#x27;s unrealistic and &#x3C;em&#x3E;expensive&#x3C;/em&#x3E;.&#x3C;/p&#x3E;

&#x3C;p&#x3E;You already disallow cell phones from being used during the movie.  It
isn&#x27;t unreasonable to extend that to all electronic devices, and then
enforce it.  That pretty well solves the problem completely and cheaply.
It&#x27;s also &#x3C;strong&#x3E;fair&#x3C;/strong&#x3E;.  I don&#x27;t want to watch a film while some douchebag
next to me is text messaging, or has an open laptop on Facebook. (I&#x27;ve
never actually witnessed the latter.)  Don&#x27;t search people and don&#x27;t
confiscate.  Just ask that when the lights do down, the devices turn
off.&#x3C;/p&#x3E;

&#x3C;p&#x3E;Long term?  Fix your policy.  It is aged, and when it punishes regular
customers instead of catching real problems, it&#x27;s time to change it.  It
makes Regal look &#x3C;em&#x3E;stupid&#x3C;/em&#x3E; when they honestly believe that a laptop is a
device capable of making a decent bootleg.&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;Film Theft:

No recording devices (cameras, video recorders, sound recorders, etc.)
are permitted to be used within any Regal Entertainment Group facility.

Personal Communication Devices:

In consideration of all our guests, Regal Entertainment group asks that
you please refrain from using cell phones, pagers, or any other personal
communication device while in the auditorium.
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;The real problem is that they are making a distinction between devices
that &#x22;record&#x22; and devices that &#x22;communicate&#x22;.  I&#x27;ve got news for you,
Regal.  They are one and the same.  That iPhone is a better recording
device than my laptop.  Real camcorders are smaller than my hand and
fit in my pocket!  You&#x27;re living in the future!  Welcome to the age of
tomorrow!&#x3C;/p&#x3E;

&#x3C;p&#x3E;For anyone that has seen &#x22;telesync&#x22; downloadable movies (aka: &#x22;cam&#x22;
movies, named for the fact that they are recorded with a camcorder), I
think we can all agree that they are generally -horrible- quality.  Once
in awhile, one looks halfway decent though.  The sound is fairly clean.
There isn&#x27;t coughing, no jerking back and forth, and it is absent of any
focus problems.  Guess why?  It was recorded from the &#x3C;em&#x3E;projectionist
booth&#x3C;/em&#x3E;, not the audience.  For an audience member to make a copy that
wouldn&#x27;t be utter garbage, they&#x27;d need to set up in the center of the
theater.  With a tripod.  And a good camcorder.  And not get caught.
Fortunately, they&#x27;d be caught when that employee came through to check
during the film... right?&#x3C;/p&#x3E;

&#x3C;p&#x3E;The only significant source of piracy equating to tangible loss of
revenue isn&#x27;t shitty cam movies causing moviegoers to stay home.  It&#x27;s
all the hands that DVD creation and distribution go through, causing
potential DVD buyers not to purchase.  To reiterate: piracy affects DVD
sales, NOT box office.&#x3C;/p&#x3E;

&#x3C;p&#x3E;Then again, maybe I can put up with a horrible telesync copy of a movie,
if it means I can watch it without being being forced into a weekly
debate.&#x3C;/p&#x3E;
</description>
</item>
<item rdf:about="http://www.martini.nu/blog/2008/12/sales.html">
<title>Sales tips for the creepy</title>
<link>http://www.martini.nu/blog/2008/12/sales.html</link>
<description>&#x3C;p&#x3E;I&#x27;ve been having a lot of door-to-door salespeople visit my house
lately, and they are exhibiting some rather disturbing tactics.  The
following is a very short guide that should help a prospective sales
dude not get &#x3C;em&#x3E;punched in the teeth&#x3C;/em&#x3E; while visiting my house.&#x3C;/p&#x3E;

&#x3C;p&#x3E;&#x3C;strong&#x3E;1) Don&#x27;t use the &#x22;shave and a haircut&#x22; knock pattern&#x3C;/strong&#x3E;&#x3C;/p&#x3E;

&#x3C;p&#x3E;That&#x27;s a knock of familiarity.  We&#x27;re not buddies.  I&#x27;m not going to
welcome you to my porch with a warm hug.  In fact, if you start out with
a knock like that, you&#x27;re immediately making me feel as if I&#x27;m being
tricked into opening the door.&#x3C;/p&#x3E;

&#x3C;p&#x3E;&#x3C;strong&#x3E;2) Don&#x27;t just say your first name when I ask who&#x27;s there&#x3C;/strong&#x3E;&#x3C;/p&#x3E;

&#x3C;p&#x3E;So, now you&#x27;ve knocked, and I ask you through the door: &#x22;Who is it?&#x22;
Please, say the name of your company -and- what you&#x27;re doing on my
porch.  Don&#x27;t respond with &#x22;David.&#x22;  Inevitably, you&#x27;ll just be asked
&#x22;David who?&#x22;, and then &#x22;What do you want, David?&#x22;&#x3C;/p&#x3E;

&#x3C;p&#x3E;Again, it seems as if you&#x27;re trying to trick me into opening the door,
and worse, you&#x27;re wasting my time while we play 20 questions.&#x3C;/p&#x3E;

&#x3C;p&#x3E;&#x3C;strong&#x3E;3) Don&#x27;t say you&#x27;re doing &#x22;word of mouth&#x22; advertising&#x3C;/strong&#x3E;&#x3C;/p&#x3E;

&#x3C;p&#x3E;It&#x27;s not word of mouth if you&#x27;re going door to door.  For the record,
that&#x27;s called &#x27;door to door&#x27;.  Word of mouth means that your &#x3C;em&#x3E;customers&#x3C;/em&#x3E;
are doing your advertising for you.  If you&#x27;re not getting paid by a
company, and you&#x27;ve discovered an AWESOME product that you just MUST go
walking around the neighborhood to tell everyone you see about... okay
then.  You&#x27;re allowed to call it word of mouth.&#x3C;/p&#x3E;

&#x3C;p&#x3E;&#x3C;strong&#x3E;4) Don&#x27;t say you aren&#x27;t selling anything&#x3C;/strong&#x3E;&#x3C;/p&#x3E;

&#x3C;p&#x3E;If I tell you &#x22;I&#x27;m not interested&#x22;, don&#x27;t reply indignantly with &#x22;Wait,
but I&#x27;m not selling anything!!&#x22;  If you&#x27;re advertising on my doorstep,
you&#x27;re selling something, even if I&#x27;m not directly giving you money
at the moment.  That&#x27;s the &#x3C;em&#x3E;definition&#x3C;/em&#x3E; of advertising.  You or your
employer has a product that they want me to have, in exchange for my
money.  If that indeed is the case and you really don&#x27;t have anything to
sell me, that just means you are a transient and have even less reason
to be hanging out at my house.  Please leave.&#x3C;/p&#x3E;

&#x3C;p&#x3E;&#x3C;strong&#x3E;5) Don&#x27;t compliment me on my children&#x3C;/strong&#x3E;&#x3C;/p&#x3E;

&#x3C;p&#x3E;Telling me how beautiful my little girls are does NOT endear me to you.
It instantly brings forth a feeling of parental terror that cascades over
me, as I realize a stranger (that knows where I live) finds my children
attractive.  This makes you appear to be predatory in a &#x3C;em&#x3E;really bad
way&#x3C;/em&#x3E;, no matter how innocent the comment actually might be.  In any
event, I certainly won&#x27;t be overcome with an intense impulse purchasing
desire.&#x3C;/p&#x3E;

&#x3C;p&#x3E;Eh, maybe it&#x27;s just time to invest in a tacky little &#x27;no soliciting&#x27;
sign.  Or a big dog.&#x3C;/p&#x3E;
</description>
</item>
<item rdf:about="http://www.martini.nu/blog/2008/11/mobile_1.html">
<title>RubyConf 2008!</title>
<link>http://www.martini.nu/blog/2008/11/mobile_1.html</link>
<description>&#x3C;p&#x3E;&#x3C;a href=&#x22;/images/blog/2008/11/1225979863656.jpg&#x22; class=&#x22;highslide&#x22; onclick=&#x22;return hs.expand(this)&#x22;&#x3E;
    &#x3C;img src=&#x22;/images/blog/2008/11/thumb_1225979863656.jpg&#x22;
    alt=&#x22;mobile post image&#x22;    /&#x3E;
&#x3C;/a&#x3E;&#x3C;/p&#x3E;

&#x3C;p&#x3E;Way more crowded than I was expecting.  Total sausage fest.  I think I saw one girl, and she was being mobbed by droves of adoring programmers.&#x3C;/p&#x3E;
</description>
</item>
<item rdf:about="http://www.martini.nu/blog/2008/10/ps3-pf.html">
<title>Tell PF to fix PS3 fragmented packets</title>
<link>http://www.martini.nu/blog/2008/10/ps3-pf.html</link>
<description>&#x3C;p&#x3E;Here&#x27;s a quickie for anyone using a &#x3C;a href=&#x22;http://www.openbsd.org/faq/pf/&#x22;&#x3E;pf&#x3C;/a&#x3E;
on their home router, and having problems with
multiplayer on a &#x3C;a href=&#x22;http://www.us.playstation.com/PS3&#x22;&#x3E;ps3&#x3C;/a&#x3E;
inside the network. Apparently, I wasn&#x27;t the &#x3C;a href=&#x22;http://www.google.com/search?q=ps3+fragment+nat&#x22;&#x3E;only
one&#x3C;/a&#x3E;.&#x3C;/p&#x3E;

&#x3C;p&#x3E;The PlayStation appears to perform packet fragmentation while leaving
the &#x3C;em&#x3E;don&#x27;t-fragment&#x3C;/em&#x3E; bit set.  Most home routers don&#x27;t seem to care --
but there are some that catch this strange behavior and not allow it
to pass. pf is generally strict about this sort of thing if you have
&#x3C;em&#x3E;scrubbing&#x3C;/em&#x3E; enabled (which is always a good idea.)&#x3C;/p&#x3E;

&#x3C;p&#x3E;Here&#x27;s a workaround to get you gaming again.&#x3C;/p&#x3E;

&#x3C;pre&#x3E;&#x3C;code&#x3E;scrub from [ps3-ip-address] to any no-df random-id fragment reassemble
&#x3C;/code&#x3E;&#x3C;/pre&#x3E;

&#x3C;p&#x3E;The only required flag here is the &#x3C;strong&#x3E;no-df&#x3C;/strong&#x3E;, which allows a packet
through that would normally be dropped.  pf recommends also ensuring IP
identifier uniqueness, which the &#x3C;strong&#x3E;random-id&#x3C;/strong&#x3E; flag enables.  I also
re-assemble the packets before forwarding them upstream, though this is
entirely optional.&#x3C;/p&#x3E;

&#x3C;p&#x3E;The nice part about this is that it only fixes up the stuff coming from
the PS3 -- you can still have the rest of your scrub rules cleaning
up nasty goop coming into your network as normal.&#x3C;/p&#x3E;

&#x3C;p&#x3E;So far, the only game that is still giving me trouble is GTA4.  I
successfully join a game about 1 in 4 tries.  Every other game I&#x27;ve
tried has been absolutely fine.&#x3C;/p&#x3E;
</description>
</item>
</rdf:RDF>



