Alixrouter med OpenBSD 5
Jag köpte en alix2d13 från pcengines.ch tillsammans med ett svart aluminiumchassis och ett 1GB SLC CF kort. Syftet var att installera OpenBSD för att bygga ett bättre hemnätverk.
Det finns många alternativ som påstår sig kunna göra just det, att installera OpenBSD på ett CF-kort. Flera kompilerar även en egen kärna med optimeringar för olika bräden, men jag upptäckte att den manuella vägen var bäst att gå, och mest lärorik.
Nätverket ska gå Internet -> gw1 (alix) -> 10/24 LAN. Routern ska ha tjänster som DHCP, DNS och PF till att börja med. Jag tänker dock inte gå igenom allt som har med DNS och PF att göra just här.
Paketet med brädet kom med allt som krävdes för att skruva ihop lådan och sätta på gummifötter, vilket var superenkelt och kul. Sedan krävdes en korsad seriell kabel, nullmodem kabel, för att få video på lådan. Jag testade en USB-adapter först eftersom både mina arbetsdatorer och min server skamligt nog saknar serieport, men fick den ej att fungera så en gammal maskin från källaren löste det.
cu -e -o -s 38400 -l /dev/cua00
Alla kommandon här körs från OpenBSD 5.0 i386, främst för att formateringen av CF-kortet ska vara från samma arkitektur som ska köras från det, men även för att det inte går att kompilera 5.0 kärnan på 4.9 just nu. Så om ni tänkte starta 5.0 i386 i vmware fusion får ni kanske tänka om, jag blev tvungen att använda Virtualbox på grund av ett fel med mtrr.
Ladda ner och kompilera OpenBSD 5
Mot all inrådan från experter ska vi kompilera en egen OpenBSD kärna. Detta steget kan faktiskt hoppas över och man kan få en fullt fungerande alix router genom att endast följa installationsteget.
# export CVSROOT=anoncvs@anoncvs.eu.openbsd.org:/cvs
# cd /usr
# cvs checkout -rOPENBSD_5_0 -P src
Nu laddas källkoden för OpenBSD 5.0-stable ner, detta tar ett tag så avancerade läsare kan gå vidare till formateringen av CF-kortet. Kan även använda sig av sys.tar.gz som en genväg.
Kompilera OpenBSD kärnan
De flesta på forumen och listorna kommer säga att man aldrig ska behöva kompilera en kärna längre, det kan säkert stämma, men jag gjorde en alix konfiguration ändå. Det sparade jag endast drygt 3MB utrymme på att göra och optimerade förmodligen inget som har med CF-kort eller chipset att göra.
Det är alltså helt valfritt.
# cd /usr/src/sys/arch/i386/conf
# cp GENERIC alix # eller använda filen som jag länkat ovan
# config alix
# cd ../compile/alix
# make clean && make
# cp bsd /bsd.alix
Kom ihåg den där /bsd.alix filen sen, det är kärnan vi ska använda på CF-kortet när det är formaterat och installerat.
Installation av Compact Flash kort
Här är det enklast att köra igång en installation på CF-kortet. Jag gör det genom att boota upp install50.iso skivan i maskinen som har CF-kortläsaren ansluten via USB. Då går man igenom en installation som liknar alla andra OpenBSD installationer förutom en sak, när man väljer disk så väljer man sd0 eller sd1, beroende på hur CF-kortet identifieras, istället för wd0.
Jag tycker om att ha en stor partition för hela systemet, och en liten för swap. Så välj custom partitioning och följ instruktionerna för disklabel.
Tryck först p och Enter, då skrivs partitionstabellen ut på skärmen. Finns där redan partitioner så ta bort dessa med d och partitionsbokstaven som argument. Till exempel d a för att radera partition a, och d b för att radera b.
Sedan skapar vi en partition a genom att köra a a. Gör storleken till hela disken utom 1, monteringspunkt /. Skapa sedan b-partitionen med a b och gör den till resten av storleken som blev över. Vi behöver ingen stor swap, den ska helst aldrig användas utan finns endast för att undvika problem. När det är färdigt skriv q för att avsluta.
Mitt första försök med detta var att köra disklabel, fdisk och newfs manuellt från ett redan installerat OpenBSD system. Den metoden fungerar men till slut var det mycket enklare att bara köra installationsprogrammet mot CF-kortet. Maila mig om ni behöver hjälp med disklabel, fdisk eller newfs.
När installationen är färdig ska CF-kortet monteras i systemet där vi kompilerade kärnan, och /bsd.alix ska kopieras över till /mnt/bsd så det skriver över den gamla kärnan.
# fdisk -y /dev/sd0a
# mount /dev/sd0a /mnt
# cp /bsd.alix /mnt/bsd
# umount /mnt
Innan avmonteringen kan även konfiguration av operativsystemet göras. Till exempel nätverkskonfiguration i etc/hostname.vr0 för första nätverkskortet så man slipper seriell konsoll för administration senare.
# cat /mnt/etc/hostname.vr0
inet 10.0.0.10 255.255.255.0 10.0.0.255 "Management"
Viktigare än så kan dock vara att redigera ''etc/boot.conf'' på kortet så att konsollen använder rätt hastighet, om man nu mot all förmodan skulle använda sig av en seriell kabel efter installationen.
# cat /mnt/etc/boot.conf
set tty com0
stty com0 38400
38400 är samma baud-hastighet som alixbrädets serieport använder, så man slipper byta mitt i anslutningen.
Redigera sedan ''etc/ttys'', ange att console ska vara on och samma baud-hastighet.
console "/usr/libexec/getty std.38400" vt220 on secure
Formatering av bootbart media i OpenBSD
Även om det var mycket enklare att installera CF-kortet med bsd.rd så blir detta en liten bonus som kan komma till nytta.
Ta först reda på geometrin av lagringsmediat med disklabel.
# disklabel sd0
type: SCSI
label: DT 101 G2
bytes/sector: 512
sectors/track: 63
tracks/cylinder: 255
sectors/cylinder: 16065
cylinders: 973
total sectors: 15644912
Har klippt ut det onödiga men disklabel visar även alla partitioner som hittas på minnet.
Man borde börja med att skriva över minnet med nollor, men det går att hoppa över och gå direkt till att redigera enheten med disklabel.
# dd if=/dev/zero of=/dev/sd0
# fdisk -iy sd0
Writing MBR at offset 0.
# disklabel -E sd0
Label editor (enter '?' for help at any prompt)
> p
OpenBSD area: 0-15644912; size: 15644912; free: 2
# size offset fstype [fsize bsize cpg]
c: 15644912 0 unused
i: 15644910 2 MSDOS
> d i
> a a
offset: [64]
size: [15631181] 15631100
FS type: [4.2BSD]
> a b
offset: [15631136]
size: [109]
FS type: [swap]
> p
OpenBSD area: 64-15631245; size: 15631181; free: 0
# size offset fstype [fsize bsize cpg]
a: 15631072 64 4.2BSD 2048 16384 1
b: 109 15631136 swap
c: 15644912 0 unused
> w
> q
I breda drag så installerar fdisk en MBR som startar på sektor 0. Sedan redigerar disklabel enheten och tar bort den befintliga MSDOS partitionen. Skapar en partition som heter a på nästan allt utrymme, och en liten som heter b för swap. Anledningen är CF-kort installation och då är swap inte viktig. Jag har även fått igång ett system utan swap men det var misstag och jag vågar inte köra skarpt utan.
Avslutar kommandona i disklabel genom att skriva ändringarna till disk och avsluta.
Nu skapar vi själva filsystemet.
# newfs -S 512 /dev/rsd0a
Enheten rsd0 tolkar jag som "real" sd0a, eller raw. Det är nytt för mig som inte använt OpenBSD på många år men jag läste mig till att filsystemet ska skapas direkt på den enheten medan den andra bara är ett smidigt alias.
Nu går det redan att montera filsystemet, och eftersom jag inte valde den här metoden att bygga routern med till sist så avslutar jag där.
# mount /dev/sd0a /mnt
Arkiven med de olika komponenterna av ett OpenBSD system som kan hämtas på FTP-speglingarna kan nu packas upp direkt i /mnt för att bygga ett system så som det hade installerats, fast utan någon konfiguration gjord.
Starta och konfigurera OpenBSD
Nu ska vi ha en komplett 5.0 installation på CF-kortet, och kanske även vår specialbyggda kärna. Stoppa i CF-kortet i alixbrädet, koppla i strömmen (köpt hos kjell som allt annat) och anslut med ethernet över korsad kabel eller switch på första nätverkskortet (längst mot DC-uttag).
Jag ska gå igenom lite av vad jag gjorde för att konfigurera routern. Alla har sitt egna tillvägagångssätt.
Först installera lite paket, konfa mina användare och nätverket.
# vim /etc/sudoers
%wheel ALL=(ALL) NOPASSWD: SETENV: ALL
# vim /etc/hostname.vr1
inet 1.2.3.4 255.255.255.0 1.2.3.255 description "Outside"
# vim /etc/hostname.vr2
inet 192.168.2.1 255.255.255.0 192.168.2.255 description "Inside"
# export PKG_PATH=ftp://ftp.eu.openbsd.org/pub/OpenBSD/5.0/packages/i386/
# pkg_add -r bash curl vim--no_x11
# chsh -s /usr/local/bin/bash root
# chsh -s /usr/local/bin/bash admin
# cat /etc/fstab
69deadbeef.b none swap sw
69deadbeef.a / ffs rw,noatime,sync 1 1
Som synes så har jag märkt de två andra gränssnitten också med ett beskrivande namn, vr1 är utsidan mot internet och vr2 är insidan mot mitt LAN. Jag föredrar även Bash som skal.
I /etc/fstab kan man stänga av access time uppdateringar på filer för att minska skrivningar till CF-kortet, samt direkt synkronisering av filsystemet så saker inte har en benägenhet att försvinna när strömmen dras ur routern. Händer något så kör OpenBSD automatiskt fsck som standard, så det brukar inte störa.
Här syns vilka tjänster jag väljer att starta, och att pf inte ska logga till /var/log/pflogd filen utan endast till gränssnittet.
# vim /etc/rc.conf.local
ntpd_flags=
named_flags="-t /var/named -u named -c /etc/named.conf"
dhcpd_flags=vr2
pflogd_flags="-s 160 -i pflog0 -f /dev/null"
sendmail_flags=NO
smtpd_flags=
Skillnaden med pflogd är att den inte sliter på CF-kortet genom att logga till en fil, utan man måste använda tcpdump live för att se paketloggen. Vilket jag föredrar i vanliga fall ändå.
# tcpdump -nettti pflog0 'tcp and port 25565'
Konfigurera ntpd
Network Time Protocol servern hjälper routern att hålla tiden, endast en rad är nödvändig i OpenBSD 5.0.
# vim /etc/ntpd.conf
server se.pool.ntp.org
server dk.pool.ntp.org
Konfigurera DNS
Named är BIND 9 på OpenBSD 5, alltså en namnserver för er oinsatta som tagit sig vatten över huvudet.
Det är ett stort ämne, jag har en enorm och gammal artikel om det redan, så jag visar bara upp de relevanta konfigurationsfilerna här.
acl lanClients {
192.168.2.0/24;
127.0.0.1;
};
acl slaveDNS {
1.2.3.5;
};
acl listenAddresses {
1.2.3.4; 192.168.2.1;
};
options {
version "";
listen-on { listenAddresses; };
empty-zones-enable yes;
recursion no;
};
include "etc/rndc.key";
controls {
inet 127.0.0.1 allow {127.0.0.1;} keys {"rndc-key";};
};
view "intranet" {
match-clients { lanClients; };
recursion yes;
notify no;
include "standard.zones";
zone "swehack.se" {
type master;
file "intranet/swehack.se";
};
};
view "internet" {
match-clients { !localnets; any; };
recursion no;
allow-transfer { slaveDNS; };
include "master.zones";
};
Views används för att kunna ha en egen version av swehack.se domänen i mitt intranät, och samtidigt erbjuda en extern version av den för alla på internet.
Ett råd angående felsökning av named, kör named -g för att se varför den inte startar, och var försiktig med rättigheter på filer i /var/named, de ska helst ägas av named gruppen eller kunna läsas/skrivas av named användaren.
Konfigurera DHCP
Jag vill att alla maskiner på mitt LAN ska kunna få en automatisk ip-adress, inget extra behöver installeras på OpenBSD för detta.
# vim /etc/dhcpd.conf
option domain-name "swehack.se";
option domain-name-servers 192.168.2.1;
subnet 192.168.2.0 netmask 255.255.255.0 {
option routers 192.168.2.1;
range 192.168.2.133 192.168.2.144;
host hempc {
hardware ethernet 0x:de:ad:be:ef;
fixed-address 192.168.2.80;
}
host server1 {
hardware ethernet 0x:de:ad:be:ef;
fixed-address 192.168.2.10;
}
# host pxe-client {
# hardware ethernet 02:03:04:05:06:07;
# filename "pxeboot";
# next-server 192.168.1.1;
# }
}
Det sista kommenterade blocket är ett bra exempel från OpenBSD på att netboota, det ska jag dock inte göra just nu. ;)
Konfigurera loggning över nätverk
Något mer som minskar på onödiga skrivningar till CF-kortet är om systemloggarna direkt skickas över nätverket till en annan maskin med billigare, mer eller stabilare lagring.
Med syslogd på OpenBSD kan det lätt konfigureras på klientsidan (router).
# vim /etc/syslogd.conf
#*.notice;auth,authpriv,cron,ftp,kern,lpr,mail,user.none /var/log/messages
kern.debug;syslog,user.info /var/log/messages
#auth.info /var/log/authlog
#authpriv.debug /var/log/secure
#cron.info /var/cron/log
#daemon.info /var/log/daemon
#ftp.info /var/log/xferlog
#lpr.debug /var/log/lpd-errs
#mail.info /var/log/maillog
#uucp.info /var/log/uucp
*.notice;auth,authpriv,cron,ftp,kern,lpr,mail,user.none @server1:514
auth,daemon,syslog,user.info;authpriv,kern.debug @server1:514
Utkommenterat alla rader utom de viktigaste meddelandena från kärnan under uppstart och syslog först, sedan lagt till två rader som talar för sig själva. servernamn:port.
Nu använder jag en Debian 6 server med rsyslog för att logga åt routern, så här konfades det.
# vim /etc/rsyslog.conf
$ModLoad imudp
$UDPServerRun 514
Det var verkligen allt som behövdes för att respektive namn som matchade något redan i rsyslog.conf skulle loggas till den angivna filen. T.ex. auth på routern finns i rsyslog.conf som auth,authpriv.*
och loggas till /var/log/auth.log. Vid omstart kommer även routerns värdnamn synas i loggarna, jag vet inte varför detta inte fungerade direkt.
PF för NAT
Jag ska endast gå igenom lite kort om vilka ändringar jag gjorde i PF för att översätta adresser mellan mitt LAN och det stora vida internätverket.
Som standard är pf.conf i pass-läge, att den släpper igenom allt utom det som uttryckligen blockeras med "block" regler. Jag ändrar alltid detta till block så att endast det man öppnar är öppet. Det kan dock ignoreras eftersom jag även lägger all min konfiguration i en egen fil så det enda jag ändrar i /etc/pf.conf är.
# vim /etc/pf.conf block include "/etc/pf.gw1"
Här ska man komma ihåg rollerna av nätverkskorten.
Vr0 är administration, intern statisk ip-adress. Vr1 är utsidan, statisk extern ip-adress. Vr2 är insidan med statisk intern ip-adress (som LAN använder för gateway).
# vim /etc/pf.gw1
MgmtIf="vr0"
OutIf="vr1"
InIf="vr2"
server1="192.168.2.80"
gw1="1.2.3.4"
LocalNetwork="192.168.2.0/26"
# Pass all traffic on internal interfaces
pass on { $MgmtIf $InIf }
# NAT out and pass anything going out from the LAN
match out log on $OutIf from $LocalNetwork to any nat-to $gw1
match out log on $OutIf from $server1 to any nat-to egress:0
pass out log on $OutIf from any to any
# Allow DNS queries from the LAN and to the gw
pass out on $OutIf proto udp all
pass in log on $OutIf proto udp from any to $OutIf:network port domain
# Allow ICMP out from the LAN
pass out log inet proto icmp all icmp-type echoreq
# Port redirection
pass in log on $OutIf proto tcp from any to $gw1 port { 22 http 25565 } rdr-to $server1
Varför där finns två rader med NAT-regler, var till en annan utgående adress, är mest för det relaterar till mitt verkliga nätverk. Dock kan jag använda det som exempel att man även kan använda speciella ord som egress för att känneteckna externa gränssnitt. Jag förmodar att detta har med default gateway att göra, det gränssnitt som är default route blir automatiskt egress (utlopp) för OpenBSD.
Att lägga till :0 på slutet betyder att ordet inte ska räkna med eventuella alias-adresser på samma gränssnitt.
Att lägga till :network efter ett gränssnittsnamn blir som att skriva 192.168.2.0/24 i det här fallet där $InIf har den adressen och det nätet.
Pass-regeln under NAT-reglerna säger att all trafik utåt från lokala nätverket är ofiltrerad på vr1.
Kör pfctl -vvnf /etc/pf.conf för att kolla efter syntaxfel och se reglerna utskrivna som de tolkas av pf. Statistik är alltid bra med pfctl -vvsr kommandot.
Som jag påpekade tidigare, ovärderlig felsökning är tcpdump -nettti pflog0 'tcpdump regler'.
OpenSMTPD
Till sist så valde jag OpenSMTPD istället för sendmail eftersom jag egentligen bara behöver lokal leverans och kanske relay i framtiden.
# cat /etc/mail/smtpd.conf
listen on lo0
listen on vr2
map "aliases" { source db "/etc/mail/aliases.db" }
accept for local alias aliases deliver to mbox
accept from local for all relay