Initial import.
authorMark Wooding <mdw@distorted.org.uk>
Thu, 20 Apr 2006 16:27:15 +0000 (17:27 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Thu, 20 Apr 2006 16:27:15 +0000 (17:27 +0100)
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
distorted.org.uk.lisp [new file with mode: 0644]
distorted.tex [new file with mode: 0644]
hibachidealers.com.lisp [new file with mode: 0644]
hosts.lisp [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..c26be56
--- /dev/null
@@ -0,0 +1,10 @@
+*.serial
+*.zone
+publish
+*.aux
+*.dvi
+*.ps
+*.log
+*.lof
+*.lot
+*.toc
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..42de330
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,43 @@
+## Makefile for mdw's zones
+
+ZONE = runlisp /home/mdw/bin/zone
+
+HIBACHI_ZONES = hibachidealers.com.zone
+DISTORTED_ZONES = \
+       distorted.org.uk.zone \
+       198.29.172.in-addr.arpa.zone \
+       199.29.172.in-addr.arpa.zone
+ALL_ZONES = \
+       $(HIBACHI_ZONES) \
+       $(DISTORTED_ZONES)
+
+DOCS = distorted.tex
+DOC_OUTPUTS = $(foreach suffix,dvi ps,\
+               $(patsubst %.tex,%.$(suffix),$(DOCS)))
+
+all: $(ALL_ZONES) $(DOC_OUTPUTS)
+
+publish:; mkdir publish
+
+install: all publish
+       for i in $(ALL_ZONES); do \
+         cmp $$i publish/$$i >/dev/null 2>&1 && continue; \
+         cp $$i publish/$$i.new && mv publish/$$i.new publish/$$i; \
+         userv root named-reload $${i%.zone}; \
+       done
+
+$(HIBACHI_ZONES): hibachidealers.com.lisp hosts.lisp
+       $(ZONE) $<
+
+$(DISTORTED_ZONES): distorted.org.uk.lisp hosts.lisp
+       $(ZONE) $<
+
+%.dvi: %.tex
+       latex $<
+       latex $<
+
+%.ps: %.dvi
+       dvips -o $@ $<
+
+clean: 
+       rm -f $(ALL_ZONES) *.toc *.lof *.lot *.log *.dvi *.ps *.aux
diff --git a/distorted.org.uk.lisp b/distorted.org.uk.lisp
new file mode 100644 (file)
index 0000000..8c7a5a3
--- /dev/null
@@ -0,0 +1,62 @@
+;;; Zone file for distorted.org.uk
+
+(load "hosts" :verbose nil)
+
+;; Network allocations
+;; (RFC1918 addresses are allocated from Cambridge G-RIN.)
+
+(defnet distorted.org.uk 172.29.198.0/23
+  (untrusted 256
+    (wireless 64))
+  (trusted 256
+    (fretwank 128
+      (unsafe 32)
+      (dhcp 32)
+      (safe 32))
+    (virtual 32)))
+
+(defhost demon 83.105.60.35)
+(defhost metalzone (unsafe 2))
+
+(setf *default-zone-admin* "hostmaster@distorted.org.uk")
+(setf *default-zone-source* 'guvnor.distorted.org.uk.)
+
+(defzone distorted.org.uk
+  ;;
+  ;; Nameservers
+  :ns ((boyle.ns :ip boyle.nsict.org)
+       (chiark.ns :ip chiark.greenend.org.uk)
+       (guvnor.ns :ip demon))
+  ;;
+  ;; Mail servers
+  ((@ lists bugs cryptomail) :mx guvnor)
+  ;;
+  ;; Colocated services
+  ((www ftp wiki) :a boyle.nsict.org)
+  ;;
+  ;; Entry is via little port-forwarding box
+  (guvnor (demon :a demon)
+         (fretwank :a (unsafe 1)))
+  ;;
+  ;; Local services
+  (bugs :a demon)
+  ;;
+  ;; Wired ethernet
+  (metalzone (fretwank :a metalzone))
+  (tubescreamer (fretwank :a (safe 1)))
+  (fuzzface (virtual :a (virtual 1)))
+  (mz (virtual :a (virtual 2)))
+  ;;
+  ;; Networks
+  (fretwank :net fretwank)
+  (dhcp :net dhcp)
+  (wireless :net wireless)
+  (virtual :net virtual))
+
+(defrevzone trusted
+  :ns ((metalzone.ns :ip metalzone))
+  :reverse trusted)
+(defrevzone untrusted
+  :ns ((metalzone.ns :ip metalzone))
+  :reverse untrusted)
+
diff --git a/distorted.tex b/distorted.tex
new file mode 100644 (file)
index 0000000..bec4f22
--- /dev/null
@@ -0,0 +1,415 @@
+\documentclass[article, a4paper, 10pt, notitlepage, numbering]{strayman}
+\usepackage[palatino, helvetica, maths=cmr]{mdwfonts}
+\usepackage[T1]{fontenc}
+\usepackage{at}
+\usepackage[mdwmargin]{mdwthm}
+\usepackage{mdwtab}
+\usepackage[all, dvips]{xy}
+
+\atdef l#1{{\normalfont\sffamily #1}}
+\atdef c#1{\textbf{#1}}
+
+\newtheorem*{observation}{Observation}
+
+\def\cbox#1{%
+  \vbox{%
+    \let\\\cr%
+    \halign{%
+      \hfil\strut\ignorespaces##\unskip\hfil\cr%
+      #1%
+      \crcr%
+    }%
+  }%
+}
+
+\errorcontextlines=999
+
+\begin{document}
+\title{@l{distorted.org.uk} network design}
+\author{Mark Wooding}
+\maketitle
+
+\thispagestyle{empty}
+\pagestyle{empty}
+
+\tableofcontents
+\listoffigures
+\listoftables
+
+\clearpage
+\pagestyle{fancy}
+
+%%%--------------------------------------------------------------------------
+\section{Concepts}
+
+We begin by defining our basic concepts.
+\begin{description}
+\item[@c{Safe}] A @c{safe} network is one whose hosts are protected from
+  potentially dangerous network traffic.  Hosts on a @c{safe} network may
+  communicate only (a) using trusted protocols (e.g., SSH) or (b) with
+  @c{trusted} hosts.
+\item[@c{Trusted}] A @c{trusted} network is one whose hosts are permitted to
+  communicate with @c{safe} networks.
+\end{description}
+
+\begin{observation}
+  It is impossible to protect hosts on a @c{safe} network from each other.
+  Therefore, a @c{safe} network must be @c{trusted}.  As an immediate
+  corollary, an @c{untrusted} network cannot be @c{safe}.
+\end{observation}
+
+We therefore distinguish three types of networks:
+\begin{enumerate}
+\item @c{Safe}, and therefore @c{trusted}.
+\item @c{Trusted} but @c{unsafe}.
+\item @c{Untrusted}, and therefore @c{unsafe}.
+\end{enumerate}
+
+
+%%%--------------------------------------------------------------------------
+\section{Existing hosts}
+
+We have the following hosts.  All of them should be @c{trusted}.
+\begin{description}
+\item[@l{metalzone}] A Linux server and desktop machine.  It is capable of
+  providing most services to the network, including mail, news, web proxying,
+  etc., and of providing services to the Internet at large.  It can also
+  provide a powerful and versatile firewall.  It should not be kept @c{safe}.
+\item[@l{tubescreamer}] A dual-boot Linux desktop and Windows desktop.  It
+  spends most of its time running Windows.  It must be kept @c{safe}.
+\item[@l{fuzzface}] A small Linux laptop.  It doesn't have enough disk
+  capacity for running services, and wouldn't be around or turned on
+  regularly enough anyway, but it is capable of firewalling itself.  We'd
+  like to attach this to a wireless network.  It need not be kept @c{safe}
+  and we'd like it to be @c{trusted}.
+\item[@l{guvnor}] An ADSL router.  It is capable of providing minimal
+  services, and it has a fairly powerful firewall built-in.  It must not be
+  kept @c{safe}.
+\item[@l{evolution}] (Not yet commissioned.)  A wireless access point.  It is
+  capable of running Linux, but due to limited memory capacity cannot provide
+  many services.  It has a powerful and versatile firewall.  It cannot be
+  kept @c{safe}.
+\end{description}
+
+We may also have guest machines.  We suspect that keeping these @c{safe}
+would be onerous to our guests, requiring configuration of web proxies and
+suchlike.  Guest machines can probably be @c{trusted}: violations of this
+trust can be rectified using a cluebat.
+
+%%%--------------------------------------------------------------------------
+\section{Structure}
+
+We require the following physical networks.
+\begin{itemize}
+\item A (wired) Ethernet, for the permanent desktop machines and servers, and
+  for any guest hosts which need physical wiring.
+\item A wireless Ethernet, for laptops.
+\end{itemize}
+
+
+\subsection{The wired network}
+
+Some hosts on our wired network (particularly @l{tubescreamer}) must be
+@c{safe}; others (e.g., @l{metalzone}) must not in order for them to do their
+jobs.  It is tempting to split the wired network into two parts: @c{unsafe}
+and @c{safe}.  But this introduces a new potential point of failure, and
+anyway fails to acknowledge the fact that both sides are already @c{trusted}.
+
+
+\subsection{The wireless network}
+
+It is important to note that the security provided by wireless networks is
+minimal, and cannot be relied upon.  Therefore a wireless network must be
+both @c{untrusted} and @c{unsafe}.  We may allow unrestricted communication
+with the global Internet, and to other @c{unsafe} networks, though hosts on
+the wireless network must not be allowed to communicate with @c{safe}
+networks.
+
+This restriction is annoying, and motivates us to introduce a @/virtual
+private network/, providing authentication and encryption; hosts on the VPN
+can be @c{trusted}, since we know who they are and (ideally) how they're
+configured.
+
+
+\subsection{Virtual private networks}
+
+As discussed earlier, we want a VPN so that hosts attached to the wireless
+network can communicate with @c{safe} hosts.  Also, we wish to participate in
+the Sinister Green VPN.  This introduces two kinds of VPN: our own can be
+@c{trusted}, but the SGVPN should not be.
+
+The question arises: should our VPN be @c{safe}?  We can see no particular
+reasons why it shouldn't be: after all, a host on the VPN already has a route
+to the global Internet (either it's communicating with us over the Internet
+already, or it's on some @c{unsafe} network).
+
+Finally, we wish to provide some @/emulated hosts/, running old operating
+systems; for example, a machine running ITS.%
+  \footnote{The Incompatible Timesharing System -- an old PDP--10 operating
+    system, which hosted MACLISP and the original EMACS implementation.}
+Such old operating systems are likely to have major security problems, and
+should be kept @c{safe} from outside attack.  It seems reasonable to place
+these emulated hosts in the @l{virtual} network, since (a)~we've just
+determined that @l{virtual} hosts should be @c{safe}, and (b)~emulated hosts
+are `virtual' in a sense anyway.
+
+
+%%%--------------------------------------------------------------------------
+\section{Networks and numbering}
+
+We therefore have the following networks.
+\begin{description}
+\item[@l{fretwank} (wired, @c{safe}/@c{unsafe} mix)] Contains @l{guvnor}
+  (router to the Internet and main firewall), @l{metalzone} (main server),
+  @l{evolution} (wireless router), and @l{tubescreamer}.  Also contains guest
+  machines allocated addresses by DHCP.
+\item[@l{wireless} (wireless, @c{untrusted})] Contains @l{fuzzface}, at least
+  sometimes, and a number of guest machines allocated addresses by DHCP;
+  @l{evolution} is its router.
+\item[@l{virtual} (virtual, @c{safe})] Contains @l{fuzzface} again, and
+  possibly various other hosts.  Not really a proper network: more a random
+  collection of point-to-point associations.  No dynamic allocation required.
+\end{description}
+See figure~\ref{fig:network} for a diagrammatic representation of the
+network, and how the various hosts fit into it.
+
+\begin{figure}
+  \[\begin{xy}
+    0; <1cm, 0cm>:
+    (0, 0) ="fwA"; (11, 0) ="fwB" **[butt][|3pt][=NET]@{-},
+    ?(.5) ="fwM" ?(.18) ="fwX" ?(.82) ="fwY",
+    "fwM" *+!U\cbox{@l{fretwank} (172.29.199.0/25)},
+    "fwM" + (0, 2) *+=(3, 1.5)[F:<12pt>][F*:green:<12pt>]
+      \cbox{@l{guvnor} \\ 83.105.60.35 \\ 172.29.199.1} ="guvnor",
+    "guvnor"; "fwM" **@{-},
+    "guvnor"; + (0, 4)
+      *+=(4, 3)[o][F][F*:red] \cbox{Global \\ Internet}
+      **@{-} ?<>(.5) *@{//} *+!L{A},
+    "fwY"; p + (0, 2)
+      *+=(3, 1.5)[F:<12pt>]\cbox{(DHCP guests)}
+      **@{-},
+    "fwY"; p - (0, 2)
+      *+=(3, 1.5)[F:<12pt>][F*:green:<12pt>]
+        \cbox{@l{evolution} \\ 172.29.198.1 \\ 172.29.199.3} ="evolution"
+      **@{-},  
+    "fwX"; p + (0, 2)
+      *+=(3, 1.5)[F:<12pt>][F*:yellow:<12pt>]
+        \cbox{@l{tubescreamer} \\ 172.29.199.65}
+      **@{-},
+    "fwX"; p - (0, 2)
+      *+=(3, 1.5)[F:<12pt>][F*:green:<12pt>]
+        \cbox{@l{metalzone} \\ 172.29.199.2} ="metalzone"
+      **@{-},
+    "metalzone" + (-3, 1) ="sgvpnA"; p - (0, 10) ="sgvpnB" **[NET]@{-},
+    ?(.5) ="sgvpnM",
+    "sgvpnM" *[left]+!R\cbox{SGO VPN (various RFC1918 addresses)},
+    "metalzone"; p - (3, 0) **@{-} ?<>(.5) *@{//} *+!U{B},
+    "metalzone" + (3, 1) ="vpnA"; p - (0, 8) ="vpnB" **[NET]@{-},
+    ?(.5) ="vpnM",
+    "vpnM" *[left]+!L\cbox{@l{virtual} (172.29.199.128/28)},
+    "metalzone"; p + (3, 0) **@{-} ?<>(.5) *@{//} *+!U{C},
+    "metalzone" - (0, 2)
+      *+=(3, 1.5)[F:<12pt>][F*:yellow:<12pt>]
+        \cbox{@l{fuzzface} \\ 172.29.199.129} ="fuzzface";
+      p + (3, 0) **@{-},
+    "fuzzface" - (0, 2)
+      *+=(3, 1.5)[F:<12pt>][F*:yellow:<12pt>]
+        \cbox{@l{mz} \\ 172.29.199.130} ="mz";
+      p + (3, 0) **@{-},
+    "mz" - (0, 2)
+      *+=(3, 1.5)[F:<12pt>]\cbox{(VPN hosts)} ="x";
+      p + (3, 0) **@{-},
+    "x" - (0, 2)
+      *+=(3, 1.5)[F:<12pt>]\cbox{(SGO hosts)} ="x";
+      p - (3, 0) **@{-},
+    "evolution" + (3, 1) ="wlanA"; p - (0, 4) ="wlanB" **[NET]@{-},
+    ?(.5) ="wlanM",
+    "wlanM" *[left]+!L\cbox{@l{wireless} (172.29.198.0/26)},
+    "evolution"; p + (3, 0) **@{-} ?<>(.5) *@{//} *+!U{D},
+    "evolution" - (0, 2)
+      *+=(3, 1.5)[F:<12pt>]\cbox{(DHCP guests)};
+      p + (3, 0) **@{-},
+  \end{xy}\]
+
+  \caption{Diagram of @l{distorted.org.uk} networks}
+  \label{fig:network}
+\end{figure}
+
+We must assign address ranges to these networks.  The @l{distorted.org.uk}
+domain has a block of 512 addresses allocated from the Cambridge G-RIN:
+172.29.198.0/23.  The low 256 addresses, 172.29.198.0/24, are used for
+@c{untrusted} hosts; the upper addresses, 172.29.199.0/24, are used for
+@c{trusted} and @c{safe} hosts.
+
+The @c{untrusted} address range is currently only used for the @l{wireless}
+network.  It is allocated 64 addresses.  This seems relatively generous:
+however, there is no small practical limit (such as the number of available
+ports on switches or hubs) on the number of hosts which can join the network.
+Since hosts on the network are granted temporary addresses via DHCP, the
+network can be resized relatively easily by reconfiguring @l{evolution}: a
+major flag day is not necessary.
+
+The @c{trusted} network is more difficult.  We start with the wired Ethernet
+@l{fretwank}.  The number of hosts which can join the Ethernet is limited by
+the number of available ports on the various switches and hubs.  Currently we
+have
+\begin{itemize}
+\item 4 ports on @l{guvnor}'s built-in switch,
+\item 8 ports on a Netgear fast Ethernet switch, and
+\item 16 ports on an old 10baseT hub,
+\end{itemize}
+for a total of 28 ports.  (In fact, the total is only 24, since four of the
+ports would be used up joining the hub and switches together.)  Hence, a
+single block of 32 addresses would suffice.  However, this makes
+administration difficult.  Instead, we allocate @/four/ groups of 32
+addresses:
+\begin{itemize}
+\item a group for @c{trusted} but @c{unsafe} hosts with fixed addresses, used
+  for servers and routers;
+\item a group for @c{safe} hosts with fixed addresses, used for our
+  vulnerable workstations;
+\item a group for @c{trusted} but @c{unsafe} hosts with addresses dynamically
+  allocated by DHCP, for guests; and
+\item a group of addresses reserved for some currently unforeseen purpose.
+\end{itemize}
+
+The VPN is at this stage allocated 32 addresses.  This can be increased
+easily should the need arise; but we envisage that the various VPN hosts will
+each need individual treatment in the firewall rules.
+
+The network address allocations are shown in detail in
+table~\ref{tab:addresses}.
+
+\begin{table}
+  \begin{tabular}[C]{|lll|}                                         \hlx{hv}
+    @*Network*       & @*Status*       & @*Address range*        \\ \hlx{vhv}
+    @l{wireless}     & @c{Untrusted}   & 172.29.198.0/26 (64)    \\ \hlx{v}
+    @l{fretwank}     & Mixture         & 172.29.199.0/25 (128)   \\
+    \quad Unsafe, fixed & @c{Trusted}  & 172.29.199.0/27 (32)    \\
+    \quad Unsafe, DHCP & @c{Trusted}   & 172.29.199.32/27 (32)   \\
+    \quad Safe       & @c{Safe}        & 172.29.199.64/27 (32)   \\
+    \quad Reserved   & ---             & 172.29.199.96/27 (32)   \\ \hlx{v}
+    @l{virtual}      & @c{Safe}        & 172.29.199.128/27 (32)  \\ \hlx{v}
+    Reserved         & ---             & $\vcenter{
+      \hbox{172.29.199.160/27 (32)}
+      \hbox{172.29.199.192/26 (64)}
+    } \Bigr\}$ (96)                                             \\ \hlx{vh}
+  \end{tabular}
+
+  \caption{Network address allocations}
+  \label{tab:addresses}
+\end{table}
+
+
+%%%--------------------------------------------------------------------------
+\section{Firewall considerations}
+
+We filter network traffic at four points, shown as
+`$\begin{xy}*+@{//}\end{xy}$' in figure~\ref{fig:network}:
+\begin{itemize}
+\item at the boundary with the global Internet, at @l{guvnor} ($A$);
+\item at the join between the @l{wireless} network and our @c{trusted}
+  networks, at @l{evolution} ($D$); and
+\item at the join between the VPNs and our @c{trusted} networks, ($B$ and
+  $C$).
+\end{itemize}
+(Technically, since we trust hosts on @l{virtual}, we needn't introduce
+filtering between it and @l{fretwank}, but doing so is cheap and relatively
+easy, and it does little harm.)
+
+The main purpose of the firewalls is to protect the hosts which are supposed
+to be @c{safe}.  Their secondary purposes are to act as an additional
+protection for @c{trusted} hosts providing services, and to limit access to
+some services to @c{trusted} hosts only.
+
+
+\subsection{Externally visible services}
+
+The server @l{metalzone} provides a number of services which need to be
+externally available: these are shown in table~\ref{tab:services}.
+
+\begin{table}
+  \centering
+  \begin{minipage}{0.8\textwidth}
+  \begin{tabular}[C]{|*{3}{ll|}}                                    \hlx{hv}
+    @*Service* & @*Port(s)* &
+      @*Service* & @*Port(s)* &
+      @*Service* & @*Port(s)*                                    \\ \hlx{vhv}
+    FTP & TCP 20, 21     & SSH & TCP 22     & SMTP & TCP 25      \\
+    DNS & TCP/UDP 53     & Finger & TCP 79  & HTTP & TCP 80      \\
+    Ident & TCP 113      & NTP & UDP 123%
+      %%\footnote{Only to upstream ISP's time servers.}
+                                            & HTTPS & TCP 443    \\
+    TrIPE & UDP 22\,003
+      & \multicolumn{2}{c|}{---}
+      & \multicolumn{2}{c|}{---}                                 \\ \hlx{vh}
+  \end{tabular}
+  \end{minipage}
+
+  \caption{Externally visible services}
+  \label{tab:services}
+\end{table}
+
+Additionally, @l{metalzone} provides a web proxy on port 3128 which should be
+available to all hosts, including @c{untrusted} hosts, whose connection to
+the global Internet is via @l{guvnor}.  (Allowing external users to use the
+proxy is bad, because they can eat up our 'net connection bandwidth very
+easily.  Disallowing @c{untrusted} hosts from using the proxy is silly,
+though, since they can @/already/ gobble the 'net connection, and using the
+proxy may help reduce the impact of many users.)
+
+Finally, @l{metalzone} supports active FTP, and occasionally other temporary
+services, on high-numbered ports.  TCP and UDP ports with numbers in the
+range 32\,000--65\,535 should be left unfiltered.
+
+
+\subsection{Trusted protocols}
+
+All hosts, including @c{safe} hosts, are permitted to contact any address on
+TCP port~22, for the purpose of setting up an SSH connection.  (Messing about
+with proxies for SSH is too tedious.)  So that this can stand a chance of
+working properly, we also allow ICMP.  This isn't, perhaps, ideal, but all
+manner of things go wrong if ICMP is blocked.  Besides, it means that @/ping/
+is likely to work, which is also useful.
+
+
+
+
+%%% A
+%%%   1. Packets from WAN
+%%%        if src-addr in rfc1918-addresses: DROP
+%%%        if src-addr in localnet: DROP
+%%%        if src-addr == guvnor.demon: DROP
+%%%        if dest-addr not in distorted-net: DROP
+%%%        if protocol == icmp: ACCEPT
+%%%        if protocol == tcp and src-port == 22 and ack: ACCEPT
+%%%        if dest-addr in fretwank-safe: DROP
+%%%        if dest-addr in vpn: DROP
+%%%        if protocol == tcp and ack: ACCEPT
+%%%        if dest-addr == metalzone.fretwank and
+%%%           protocol/dest-port in external-services:
+%%%          ACCEPT
+%%%        DENY
+%%%
+%%%   2. Packets from LAN
+%%%      if src-addr not in distorted-net: DROP
+%%%      ACCEPT
+
+%%% D
+%%%   1. Packets from WLAN
+%%%        if src-addr not in wireless: DROP
+%%%        if dest-addr not in distorted-net: DROP
+%%%        if protocol == icmp: ACCEPT
+%%%        if protocol == tcp and src-port == 22 and ack: ACCEPT
+%%%        if dest-addr in fretwank-safe: DROP
+%%%        if dest-addr in vpn: DROP
+%%%        if protocol == tcp and ack: ACCEPT
+%%%        if dest-addr == metalzone.fretwank and
+%%%           (protocol/dest-port in external-services or
+%%%            protocol == tcp and dest-port == 3128):
+%%%          ACCEPT
+%%%        DENY
+%%%
+
+
+\end{document}
diff --git a/hibachidealers.com.lisp b/hibachidealers.com.lisp
new file mode 100644 (file)
index 0000000..87554e1
--- /dev/null
@@ -0,0 +1,22 @@
+;;; Zone source for hibachidealers.com
+
+(load "hosts" :verbose nil)
+
+(setf *default-zone-source* 'guvnor.distorted.org.uk.)
+
+(defzone hibachidealers.com
+  ;;
+  ;; Name servers
+  :ns ((boyle.ns :ip boyle.nsict.org)
+       (chiark.ns :ip chiark.greenend.org.uk)
+       (mccoy.ns :ip mccoy.flatline.org.uk))
+  (guvnor.ns :a guvnor.distorted.org.uk)
+  ;;
+  ;; Colocated services
+  ((@ www www-test) :a boyle.nsict.org)
+  ;;
+  ;; Mail servers
+  :mx ((guvnor.mx :ip guvnor.distorted.org.uk))
+)
+
+  
\ No newline at end of file
diff --git a/hosts.lisp b/hosts.lisp
new file mode 100644 (file)
index 0000000..c98c133
--- /dev/null
@@ -0,0 +1,6 @@
+;; Static IP addresses for various useful hosts
+
+(defhost guvnor.distorted.org.uk 83.105.60.35)
+(defhost boyle.nsict.org 85.158.42.162)
+(defhost chiark.greenend.org.uk 193.201.200.170)
+(defhost mccoy.flatline.org.uk 80.74.241.31)