Golem

This document describes how to build Golem, a multi-function server. Golem runs on commodity router hardware and provides a number of features:

  • SSH access
  • a media service compatible with iTunes
  • a file share
  • an LDAP and Kerberos service
  • a network proxy
  • a NetFlow collector

We build Golem on top of OpenWrt because of the distribution’s simplicity and small size. Golem is made up of roughly 120 packages, and its programs and configurations take up less than 50 MB of storage space. Here we assume that Golem will run within the confines of a Xen hypervisor.

Establish the Golem VM

Perform the following steps on the Xen Dom0 host to establish the VM which will host Golem:

  1. Obtain the x86_64 OpenWrt image at https://downloads.lede-project.org/releases/17.01.1/targets/x86/64/lede-17.01.1-x86-64-combined-ext4.img.gz.
  2. Uncompress the image and place it at /var/lib/xen/images/golem-lede-17.01.1-x86-64-combined-ext4.img on the Xen Dom0 host.
  3. Create a disk image to serve as the server’s large data store (see our notes on platform virtualization) and name it /var/lib/xen/images/golem-data.qcow.
  4. Write the following at /etc/xen/vm-golem.cfg on the Xen Dom0 host (replace XX:XX:XX:XX:XX:XX):
name    = "golem"
memory  =  1024
vcpus   =  1
builder = "hvm"
vif     = [ "model=e1000,script=vif-bridge,bridge=xenbr0,mac=XX:XX:XX:XX:XX:XX" ]
disk    = [
  "tap2:tapdisk:aio:/var/lib/xen/images/golem-lede-17.01.1-x86-64-combined-ext4.img,xvda,w",
  "tap2:qcow:/var/lib/xen/images/golem-data.qcow,xvdb,w"
          ]
serial  = "pty"

Software installation

Perform the following steps on Golem:

  1. Set the root password: passwd.
  2. Remove unnecessary packages:
opkg remove \
        dnsmasq \
        kmod-ppp \
        kmod-pppoe \
        kmod-pppox \
        kmod-r8169 \
	logd \
	luci \
        luci-app-firewall \
        luci-base \
        luci-lib-ip \
        luci-lib-nixio \
        luci-proto-ipv6 \
        luci-proto-ppp \
        luci-theme-bootstrap \
        mtd \
        odhcpd-ipv6only \
        ppp \
        ppp-mod-pppoe \
        r8169-firmware \
        uhttpd-mod-ubus \
	uhttpd
  1. Configure networking by writing /etc/config/network:
config interface loopback
	option ifname lo
	option proto static
	option ipaddr 127.0.0.1
	option netmask 255.0.0.0

config interface lan
	option ifname eth0
	option proto dhcp
  1. Install the necessary software:
opkg update
opkg install \
	block-mount \
	ca-certificates \
	dmapd \
	freifunk-watchdog \
	gst1-mod-app \
	gst1-mod-audioconvert \
	gst1-mod-audioparsers \
	gst1-mod-flac \
	gst1-mod-gio \
	gst1-mod-id3demux \
	gst1-mod-lame \
	gst1-mod-mpeg2dec \
	gst1-mod-mpg123 \
	gst1-mod-ogg \
	gst1-mod-playback \
	gst1-mod-theora \
	gst1-mod-typefindfunctions \
	gst1-mod-vorbis \
	krb5-server \
	nfdump \
	nfs-kernel-server \
	openldap-server \
	rsync \
	syslog-ng \
	tinyproxy \
	zoneinfo-core \
	zoneinfo-northamerica
  1. Install a public SSH key at /etc/dropbear/authorized_keys.

Configuring Kerberos authentication

  1. /etc/krb5.conf (replace EXAMPLE.COM):
[libdefaults]
	default_realm = EXAMPLE.COM
	dns_lookup_realm = false
	dns_lookup_kdc = false
	ticket_lifetime = 24h
	forwardable = yes

[realms]
	EXAMPLE.COM = {
		kdc = localhost:88
		admin_server = localhost:749
		default_domain = local
	}

[domain_realm]
	.local = EXAMPLE.COM
	local = EXAMPLE.COM
  1. Add Kerberos principals by running kadmin.local and then add_principal user for each user.

Configuring LDAP network information

  1. /etc/openldap/example.com.cert: Place your certificate in /etc/openldap/example.com.cert.

  2. /etc/openldap/example.com.key: Place your private key in /etc/openldap/example.com.key.

  3. /etc/openldap/ca.cert: Place your CA certificate in /etc/openldap/ca.cert.

  4. /etc/openldap/slapd.conf (replace PASSWORD and example.com):

include         /etc/openldap/schema/core.schema
include         /etc/openldap/schema/cosine.schema
include         /etc/openldap/schema/inetorgperson.schema
include         /etc/openldap/schema/nis.schema
include         /etc/openldap/schema/autofs.schema
include         /etc/openldap/schema/sudoers.schema

allow bind_v2

TLSCACertificateFile /etc/openldap/ca.cert
TLSCertificateFile /etc/openldap/example.com.cert
TLSCertificateKeyFile /etc/openldap/example.com.key

pidfile         /var/run/slapd.pid
argsfile        /var/run/slapd.args

database        ldif
directory	/etc/openldap/db
suffix          "dc=example,dc=com"
rootdn          "cn=Manager,dc=example,dc=com"
rootpw          PASSWORD
  1. /etc/openldap/schema/sudoers.schema:
attributetype ( 1.3.6.1.4.1.15953.9.1.1
	NAME 'sudoUser'
	DESC 'User(s) who may  run sudo'
	EQUALITY caseExactIA5Match
	SUBSTR caseExactIA5SubstringsMatch
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

attributetype ( 1.3.6.1.4.1.15953.9.1.2
	NAME 'sudoHost'
	DESC 'Host(s) who may run sudo'
	EQUALITY caseExactIA5Match
	SUBSTR caseExactIA5SubstringsMatch
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

attributetype ( 1.3.6.1.4.1.15953.9.1.3
	NAME 'sudoCommand'
	DESC 'Command(s) to be executed by sudo'
	EQUALITY caseExactIA5Match
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

attributetype ( 1.3.6.1.4.1.15953.9.1.4
	NAME 'sudoRunAs'
	DESC 'User(s) impersonated by sudo'
	EQUALITY caseExactIA5Match
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

attributetype ( 1.3.6.1.4.1.15953.9.1.5
	NAME 'sudoOption'
	DESC 'Options(s) followed by sudo'
	EQUALITY caseExactIA5Match
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

attributetype ( 1.3.6.1.4.1.15953.9.1.6
	NAME 'sudoRunAsUser'
	DESC 'User(s) impersonated by sudo'
	EQUALITY caseExactIA5Match
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

attributetype ( 1.3.6.1.4.1.15953.9.1.7
	NAME 'sudoRunAsGroup'
	DESC 'Group(s) impersonated by sudo'
	EQUALITY caseExactIA5Match
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

attributetype ( 1.3.6.1.4.1.15953.9.1.8
	NAME 'sudoNotBefore'
	DESC 'Start of time interval for which the entry is valid'
	EQUALITY generalizedTimeMatch
	ORDERING generalizedTimeOrderingMatch
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )

attributetype ( 1.3.6.1.4.1.15953.9.1.9
	NAME 'sudoNotAfter'
	DESC 'End of time interval for which the entry is valid'
	EQUALITY generalizedTimeMatch
	ORDERING generalizedTimeOrderingMatch
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )

attributeTypes ( 1.3.6.1.4.1.15953.9.1.10
	NAME 'sudoOrder'
	DESC 'an integer to order the sudoRole entries'
	EQUALITY integerMatch
	ORDERING integerOrderingMatch
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )

objectclass ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL
	DESC 'Sudoer Entries'
	MUST ( cn )
	MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $
		sudoRunAsGroup $ sudoOption $ sudoNotBefore $ sudoNotAfter $
		sudoOrder $ description )
	)
  1. From a computer with ldapadd on golem’s network, execute ldapadd -x -D "cn=Manager,dc=example,dc=com" -W -f accounts.ldif, where accounts.ldif contains records like (replace example, com, user, and Some User):
dn: dc=example,dc=com
objectClass: organization
objectClass: dcObject
o: Example Organization
dc: example

dn: automountMapName=auto_master,dc=example,dc=com
objectClass: top
objectClass: automountMap
automountMapName: auto_master

dn: automountMapName=auto_root,dc=example,dc=com
objectClass: top
objectClass: automountMap
automountMapName: auto_root

dn: automountKey=/-,automountMapName=auto_master,dc=example,dc=com
objectClass: top
objectClass: automount
automountKey: /-
automountInformation: auto_root

dn: automountKey=/home,automountMapName=auto_root,dc=example,dc=com
objectClass: top
objectClass: automount
automountKey: /home
automountInformation: golem.example.com:/home/

dn: ou=group,dc=example,dc=com
objectClass: organizationalUnit
ou: group

dn: cn=ldapusers,ou=group,dc=example,dc=com
objectClass: posixGroup
objectClass: top
cn: ldapusers
userPassword:: WFhYWA==
gidNumber: 1002

dn: ou=people,dc=example,dc=com
objectClass: organizationalUnit
ou: people

dn: uid=user,ou=people,dc=example,dc=com
uid: user
cn: Some User 
objectClass: account
objectClass: posixAccount
objectClass: top
userPassword:: WFhYWA==
loginShell: /bin/bash
uidNumber: 1102
gidNumber: 1002
homeDirectory: /home/user
gecos: Some User

dn: ou=sudoers,dc=example,dc=com
objectClass: top
objectClass: organizationalUnit
ou: sudoers

dn: cn=user,ou=sudoers,dc=example,dc=com
objectClass: top
objectClass: sudoRole
cn: user
sudoUser: user
sudoHost: ALL
sudoCommand: ALL

Configuring the dmapd media server

  1. /etc/dmapd.conf:
[General]
Database-Dir=/mnt/sda1/var/dmapd

[Music]
Type=DAAP
Dirs=/mnt/sda1/Storage/Music/
Transcode-Mimetype=audio/mp3

[Picture]
Type=DPAP
Dirs=/mnt/sda1/Storage/Pictures/

Configuring NFS

  1. /etc/exports:
/mnt/sda1 *(fsid=root,rw,insecure,no_subtree_check,async)
/mnt/sda1/Storage *(rw,insecure,no_subtree_check,async)
/mnt/sda1/home *(rw,insecure,no_subtree_check,async)

Configuring Tinyproxy

  1. /etc/tinyproxy-filter.conf: List the websites that you want tinyproxy to allow access to, one per line (e.g., www.example.com).

Configure the firewall

  1. /etc/config/firewall:
config defaults
        option drop_invalid 1
        option input ACCEPT
        option output ACCEPT
        option forward ACCEPT

config zone
        option name lan
        option network lan
        option input ACCEPT
        option output ACCEPT
        option forward DROP

Configure basic system settings

  1. /etc/config/fstab:
config global automount
	option from_fstab 1
	option anon_mount 1

config global autoswap
	option from_fstab 1
	option anon_swap  1
  1. /etc/config/nfs:
config nfs nfs
	option minversion '4'
  1. /etc/config/system:
config system
	option hostname	golem.example.com
	option timezone	EST5EDT,M3.2.0,M11.1.0

config timeserver ntp
        list server     0.openwrt.pool.ntp.org
        list server     1.openwrt.pool.ntp.org
        list server     2.openwrt.pool.ntp.org
        list server     3.openwrt.pool.ntp.org
        option enabled 1
        option enable_server 0
  1. /etc/config/tinyproxy:
config tinyproxy

option enable 1
option User nobody
option Group nogroup
option Port 8080
option Timeout 600
option SysLog 1
option LogLevel Info
option MaxClients 100
option MinSpareServers 1
option MaxSpareServers 3
option StartServers 1
option MaxRequestsPerChild 0
option ViaProxyName "tinyproxy"
option Filter "/etc/tinyproxy-filter.conf"
option FilterDefaultDeny 1
  1. /etc/config/freifunk-watchdog:
config process
	option process dropbear	
	option initscript /etc/init.d/dropbear

config process
        option process crond
        option initscript '/etc/init.d/cron'
	
config process
	option process dmapd
	option initscript /etc/init.d/dmapd	

config process
	option process krb5kdc
	option initscript /etc/init.d/krb5kdc
	
config process
	option process slapd
	option initscript /etc/init.d/ldap
  1. /etc/config/network:
config interface loopback
	option ifname lo
	option proto static
	option ipaddr 127.0.0.1
	option netmask 255.0.0.0

config interface lan
	option ifname eth0
	option proto dhcp
  1. /etc/config/dropbear:
config dropbear
	option PasswordAuth 'off'
	option RootPasswordAuth 'off'
	option Port         '22'
  1. /etc/config/nfcapd:
config nfcapd nfcapd
	option enabled 1
	option port 9995
	option logdir /mnt/sda1/var/log/netflow

My research interests include free and open source software, system security, and network security.