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
    
  3. 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

  4. 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
    
  5. 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

  2. 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

  5. /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 ) )

  6. 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

  2. /etc/config/nfs:
    config nfs nfs
    	option minversion '4'
    
  3. /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

  4. /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

  5. /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

  6. /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

  7. /etc/config/dropbear:
    config dropbear
    	option PasswordAuth 'off'
    	option RootPasswordAuth 'off'
    	option Port         '22'
    
  8. /etc/config/nfcapd:
    config nfcapd nfcapd
    	option enabled 1
    	option port 9995
    	option logdir /mnt/sda1/var/log/netflow
    
Avatar
W. Michael Petullo

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