Trial1 Server Software

From OLPC
Jump to: navigation, search
  This page is monitored by the OLPC team.

This page describes the software for a quick first prototype of the School server, intended for use in trials of the XO laptop using Trial1 Software. This is not necessarily representative of the system OLPC plans to ship in production, it contains many simplifications to speed prototyping.

This software has been superseded by the XS Server Software.

Target Platform

The target platforms for this software are:

  • An XO laptop (AMD Geode) -- An image to start with
  • A conventional desktop machine (Intel or AMD 586+)
  • XSX, a dozen early prototypes (hardware selection ongoing)
  • developer boards for processors under consideration

At least 128 MB of memory (and a storage device capable of supporting virtual memory) is required. 256 MB or more is suggested.

The storage device may be attached using:

  • SATA
  • IDE (PATA)
  • USB

The networking interfaces will be varied. Each server will support up to three Marvell wireless mesh networking modules connected via USB 2.0. In addition, at least two 100baseT network intefaces will be provided for connection to the WAN and LAN. These may also be connected via USB.

No graphics capabilities are planned. If a server (such as a desktop machine) has an attached keyboard and display, they will used for a text console.

Installation

It has been suggested that Pilgrim be used for building bootable images of the server software.

Disk Partitions

The OS and applications should have the root partition, initialized by the disk image. /dev is provided by udev, /proc and /sys by the kernel.

The disk formatting is:

  • a root partition of 8 GB,
  • a boot partition of 100 MB,
  • a swap partition of 2 GB,
  • the remainder of the disk should be a single partition, mounted through the Logical Volume Manager (LVM), and assigned to /library.

A logical volume manager will be used to manage the storage used by students and library content. One logical volume will be used, which will use a second partition on the disk.

Manifest

This is the software manifest for the school server.

OS

The software will be based on Fedora Core 6. Where no explicit version information is provided for software, the version included in FC6 should be assumed.

We will be running a recent kernel (currently 2.6.20.), capable of booting on both the laptop and a more conventional desktop machine.

Interpreters

Perl

Python

Python 2.4 for now. When the laptop transitions to 2.5 (before release in September ?), the server will as well.

Database Servers

MySQL

MySQL will be provided for use by local services. Access will be limited to localhost.

SQLite

SQLite 3 will be provided.

Web Server

Apache2 will be provided.

Installed modules will include:

  • mod_perl
  • mod_php
  • mod_include

Moodle

Moodle will provide tools for teachers.

Martin Langhoff will help with this once we have an image ?

Moodle may provide a solution for some of the school administration tasks as well.

MediaWiki

MediaWiki will be installed on the server, and made available at: http://schoolserver/wiki/

Content (SJ) will provide default content. How is this packaged and installed ?

MoinMoin

MoinMoin will be installed on the server.

Networking

Sketch of the school server and three mesh segments of laptops Trial1 School Network (printable version)

A single school server will be deployed in these initial installations, simplifying the network. Between two and three wireless mesh network interfaces will be deployed, attached to the school server via USB. Two wired networking interfaces will also be provided, for connection to the Internet via a WiFi interface or DSL, satellite, or 2.5G/3G modem.

The laptops will be assigned an IP address using DHCP.

Network Interfaces

Currently, we are providing each school server with two wired interfaces, eth0 and eth1. Additional mesh interfaces will be located at msh0/eth2, msh1/eth3, and msh2/eth4. The Fedora network scripts are being used. The interface configuration scripts currently look like:

/etc/sysconfig/network-scripts/ifcfg-wan

DEVICE=eth0
# sn: 002
 HWADDR=00:40:63:E9:99:9B
# In a real schoolserver, we are likely to DHCP
BOOTPROTO=dhcp
#  Sometimes, a static address is assigned
# IPADDR=18.85.46.32
# NETMASK=255.255.255.0
# NETWORK=18.85.46.0
# BROADCAST=18.85.46.255
# GATEWAY=18.85.46.1
ONBOOT=yes
DHCP_HOSTNAME=schoolserver1

/etc/sysconfig/network-scripts/ifcfg-lan

DEVICE=eth1
# sn: 002 D-Link DFE-530TX+
HWADDR=00:19:5B:68:9D:4E
IPADDR=172.18.0.1
NETMASK=255.255.240.0
NETWORK=172.18.0.0
BROADCAST=172.18.15.255
ONBOOT=yes

/etc/sysconfig/network-scripts/ifcfg-msh0

#  Marvell mesh network module, mesh side
#  (this device also appears as ethN+2)
DEVICE=msh0
#  Ideally, this would work:
# MACADDR=00:17:C4:00:00:01
MODE=ad-hoc
CHANNEL=1
ESSID="olpc-mesh-1"
IPADDR=172.18.16.1
NETMASK=255.255.240.0
NETWORK=172.18.16.0
BROADCAST=172.18.31.255
ONBOOT=yes 

/etc/sysconfig/network-scripts/ifcfg-eth2

#  Marvell mesh network module, infrastructure mode side
#  (this device also appears as mshN-2)
DEVICE=eth2
MACADDR=00:17:C4:00:00:01
ONBOOT=yes

/etc/sysconfig/network-scripts/ifcfg-msh1

#  Marvell mesh network module, mesh side
#  (this device also appears as ethN+2)
DEVICE=msh1
#  Ideally, this would work:
# MACADDR=00:17:C4:00:00:02
MODE=ad-hoc
CHANNEL=11
ESSID="olpc-mesh-2"
IPADDR=172.18.32.1
NETMASK=255.255.240.0
NETWORK=172.18.32.0
BROADCAST=172.18.47.255
ONBOOT=yes

/etc/sysconfig/network-scripts/ifcfg-msh2

#  Marvell mesh network module, mesh side
#  (this device also appears as ethN+2)
DEVICE=msh2
#  Ideally, this would work:
# MACADDR=00:17:C4:00:00:03
MODE=ad-hoc
CHANNEL=6
ESSID="olpc-mesh-3"
IPADDR=172.18.48.1
NETMASK=255.255.240.0
NETWORK=172.18.48.0
BROADCAST=172.18.63.255
ONBOOT=yes

ifcfg-eth3 and ifcfg-eth4 are identical (except for the MAC address assigned) to ifcfg-eth2

The ad-hoc side of the Marvell wireless network interface is brought up only to assign a new MAC address to the Marvell modules being used by the School server. They are development boards, and don't have the "proper" MAC address prefix for the laptops to associate with. With the current driver, this MAC address reassignment can only be done on the ad-hoc interface, not the mesh interface.

Routing, Filtering & Masquerading

The server is tasked with routing between the different network segments attached to it. These include:

  • MSH0/1/2 - Between one and three mesh network segments
  • LAN - A wired network segment, which may include standalone APs.
  • WAN - A wired/wireless segment which connects us to an internet gateway

Masquerading of source address, or NAT, is applied to packets routed between the internal segments (LAN and MSH) and the WAN segment. All networked machines in the school appear as a single address on the internet, that of the primary school server.

NAT

Network Address Translation (NAT) and Port Address Translation will be provided on the network interface connecting to the Internet

These mechanisms allow all of the laptops in the school to share a single IP address. Fedora's native iptable startup script is used, which relies on two configuration files: /etc/sysconfig/iptables-conf (which identifies modules to load and the behavior of the startup script -- we don't ever save out the running configuration) and /etc/sysconfig/iptables.

The current firewall provides NAT functionality. Devices on the LANs (wired or mesh) may initiate outgoing connections. Tracked protocols (those which the NAT understands and supports) include:

  • FTP
  • IRC
  • SIP
  • PPTP
  • H.323

Filtering

Incoming traffic to the school server from the WAN (Internet) is allowed on the following ports:

  • SSH (22)
  • HTTP (80)
  • HTTPS (443)

Incoming traffic to the school server from the LANs (wired or mesh) is allowed on the following ports:

  • SSH (22)
  • HTTP (80)
  • HTTPS (443)
  • DNS (53)
  • BOOTP (67/68)
  • NTP (123)
  • MPP (16, used by mesh portal protocol)
  • in addition, select ICMP packets are accepted

The /etc/sysconfig/iptables file is currently:

#  iptables for schoolserver firewall
#  Trial1 version
#
#  OLPC, April 2007
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A POSTROUTING -o eth0 -j MASQUERADE 
COMMIT
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:allowed_icmp - [0:0]
-A INPUT -i lo -j ACCEPT 
-A INPUT -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT 
-A INPUT -i eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT 
-A INPUT -i msh0 -m state --state RELATED,ESTABLISHED -j ACCEPT 
-A INPUT -i msh1 -m state --state RELATED,ESTABLISHED -j ACCEPT 
-A INPUT -i msh2 -m state --state RELATED,ESTABLISHED -j ACCEPT 
-A INPUT -i eth1 -p udp -m udp --dport 53 -j ACCEPT 
-A INPUT -i eth1 -p tcp -m tcp --dport 53 -j ACCEPT 
-A INPUT -i msh0 -p udp -m udp --dport 53 -j ACCEPT 
-A INPUT -i msh0 -p tcp -m tcp --dport 53 -j ACCEPT 
-A INPUT -i msh0 -p udp -m udp --dport 16 -j ACCEPT 
-A INPUT -i msh1 -p udp -m udp --dport 53 -j ACCEPT 
-A INPUT -i msh1 -p tcp -m tcp --dport 53 -j ACCEPT 
-A INPUT -i msh1 -p udp -m udp --dport 16 -j ACCEPT 
-A INPUT -i msh2 -p udp -m udp --dport 53 -j ACCEPT 
-A INPUT -i msh2 -p tcp -m tcp --dport 53 -j ACCEPT 
-A INPUT -i msh2 -p udp -m udp --dport 16 -j ACCEPT 
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT 
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT 
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT 
-A INPUT -i eth1 -p udp -m udp --dport 123 -j ACCEPT 
-A INPUT -i msh0 -p udp -m udp --dport 123 -j ACCEPT 
-A INPUT -i msh1 -p udp -m udp --dport 123 -j ACCEPT 
-A INPUT -i msh2 -p udp -m udp --dport 123 -j ACCEPT 
-A INPUT -i eth1 -p udp -m udp --sport 68 --dport 67 -j ACCEPT 
-A INPUT -i msh0 -p udp -m udp --sport 68 --dport 67 -j ACCEPT 
-A INPUT -i msh1 -p udp -m udp --sport 68 --dport 67 -j ACCEPT 
-A INPUT -i msh2 -p udp -m udp --sport 68 --dport 67 -j ACCEPT 
-A INPUT -p icmp -j allowed_icmp 
-A INPUT -d 255.255.255.255 -j DROP 
-A INPUT -d 224.0.0.251 -j DROP 
-A INPUT -j LOG 
-A INPUT -j DROP 
-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT 
-A FORWARD -i eth1 -m state --state NEW -j ACCEPT 
-A FORWARD -i msh0 -m state --state NEW -j ACCEPT 
-A FORWARD -i msh1 -m state --state NEW -j ACCEPT 
-A FORWARD -i msh2 -m state --state NEW -j ACCEPT 
-A FORWARD -p icmp -j allowed_icmp 
-A FORWARD -d 255.255.255.255 -j DROP 
-A FORWARD -d 224.0.0.251 -j DROP 
-A FORWARD -j LOG 
-A FORWARD -j DROP 
-A OUTPUT -o lo -j ACCEPT 
-A OUTPUT -j ACCEPT 
-A allowed_icmp -p icmp -m icmp --icmp-type 8 -j ACCEPT 
-A allowed_icmp -p icmp -m icmp --icmp-type 0 -j ACCEPT 
-A allowed_icmp -p icmp -m icmp --icmp-type 4 -j ACCEPT 
-A allowed_icmp -p icmp -m icmp --icmp-type 11 -j ACCEPT 
-A allowed_icmp -p icmp -m icmp --icmp-type 3 -j ACCEPT 
-A allowed_icmp -p icmp -m icmp --icmp-type 12 -j ACCEPT 
COMMIT

We are logging dropped packets, to aid in debugging, yet the very common broadcast and multicast packets are dropped before logging to avoid overwhelming the log.

Doubtlessly there are ports we should have open, but don't. Send your requests to server-devel AT laptop.org.

I still need to wire squid into forwards with a dport of 80. These are redirected to the school server's port 3128, where the Squid HTTP cache will be listening.

Forwarding was enabled by editing /etc/sysctl.conf to be:

# OLPC School server Kernel sysctl configuration file
#
# Forward packets
net.ipv4.ip_forward = 1

# Perform source route verification
net.ipv4.conf.default.rp_filter = 1

# Do not accept source routing
net.ipv4.conf.default.accept_source_route = 0

# Controls the System Request debugging functionality of the kernel
kernel.sysrq = 0

# Controls whether core dumps will append the PID to the core filename.
# Useful for debugging multi-threaded applications.
kernel.core_uses_pid = 1

# Controls the use of TCP syncookies
net.ipv4.tcp_syncookies = 1

Bridging vs. Routing

There was a strong temptation to declare the individual network segments part of the same subnet and bridge between them. There are two reasons why this was not done:

  • The mesh point portal (MPP) discovery protocol would not be bridged properly unless we enabled ebtables and added explicit bridge filtering to forward it. See the Mesh Portal discovery protocol for more details.
  • Broadcast and multicast traffic from hundreds of laptops could overwhelm the network if bridged. We were willing to test this, but discovered that our MPP protocol didn't work with a bridge and moved to routing.

Instead, each mesh (and the wired LAN) are declared as individual subnets and routing occurs between them. The main impact of this being that broadcast and multicast packets will not be relayed between wireless mesh segments. In cases where it is determined that this poses a problem, we may explicitly route some multicast packets between mesh segments.

Mesh Portal

The server functions as a Mesh Portal on the mesh networks of which it is a member. The implications of this are discussed in the Mesh Portal discovery protocol.

It does this using the following server, mpp_server.py:

#!/usr/bin/python
# Derived from code, copyright 2006, Marvell Semiconductor, Inc.
# Author: Luis Carlos Cobo <luisca@cozybit.com>
# GPL license
 
import socket, traceback, commands, syslog, os, sys

ANY_MPP_IP="172.31.255.254"
MPPREQ_PORT=16

host = 
port = MPPREQ_PORT

dnss='172.18.0.1'
mesh_iface_a='msh0'
mesh_addr_a='172.18.16.1'
mesh_iface_b='msh1'
mesh_addr_b='172.18.32.1'
mesh_iface_c='msh2'
mesh_addr_c='172.18.48.1'

# Default daemon parameters.
# File mode creation mask of the daemon.
UMASK = 0

# Default working directory for the daemon.
WORKDIR = "/"

# Default maximum for the number of available file descriptors.
MAXFD = 1024

# The standard I/O file descriptors are redirected to /dev/null by default.
if (hasattr(os, "devnull")):
   REDIRECT_TO = os.devnull
else:
   REDIRECT_TO = "/dev/null"

def createDaemon():
   """Detach a process from the controlling terminal and run it in the
   background as a daemon.
   """

   try:
       pid = os.fork()
   except OSError, e:
       raise Exception, "%s [%d]" % (e.strerror, e.errno)

   if (pid == 0):   # The first child.
       # We will almost certainly not receive a HUP at this point,
       # unless we stop executing due to failure.
       # import signal           # Set handlers for asynchronous events.
       # signal.signal(signal.SIGHUP, signal.SIG_IGN)
       
       try:
           pid = os.fork()# Fork a second child.
       except OSError, e:
           raise Exception, "%s [%d]" % (e.strerror, e.errno)
       
       if (pid == 0):   # The second child.
           # Since the current working directory may be a mounted filesystem,
           # we avoid the issue of not being able to unmount the filesystem at
           # shutdown time by changing it to the root directory.
           os.chdir(WORKDIR)
           os.umask(UMASK)
       else:
           os._exit(0)  # Exit parent (the first child) of the second child.
   else:
       os._exit(0)# Exit parent of the first child.
       
   # Close all open file descriptors.
   # Use the getrlimit method to retrieve the maximum file descriptor
   # number that can be opened by this process.  If there is not limit
   # on the resource, use the default value.
   #
   import resource     # Resource usage information.
   maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
   if (maxfd == resource.RLIM_INFINITY):
       maxfd = MAXFD
       
   # Iterate through and close all file descriptors.
   for fd in range(0, maxfd):
       try:
           os.close(fd)
       except OSError: # ERROR, fd wasn't open to begin with (ignored)
           pass
       
   # Redirect the standard I/O file descriptors to the specified file.  Since
   # the daemon has no controlling terminal, most daemons redirect stdin,
   # stdout, and stderr to /dev/null.  This is done to prevent side-effects
   # from reads and writes to the standard I/O file descriptors.
   
   # This call to open is guaranteed to return the lowest file descriptor,
   # which will be 0 (stdin), since it was closed above.
   os.open(REDIRECT_TO, os.O_RDWR)    # standard input (0)
   
   # Duplicate standard input to standard output and standard error.
   os.dup2(0, 1)# standard output (1)
   os.dup2(0, 2)# standard error (2)
   return(0)

if __name__ == "__main__":
   retCode = createDaemon()

   syslog.openlog( 'mpp', 0, syslog.LOG_DAEMON )
   syslog.syslog( 'starting server' )
   mymessage_a='IPv4-0\n' + mesh_addr_a + '\n' + dnss + '\n'
   mymessage_b='IPv4-0\n' + mesh_addr_b + '\n' + dnss + '\n'
   mymessage_c='IPv4-0\n' + mesh_addr_c + '\n' + dnss + '\n'

   # Start MPP functionality in mesh firmware
   commands.getoutput('echo 1 > /sys/class/net/' + mesh_iface_a + '/libertas_mpp')
   commands.getoutput('echo 1 > /sys/class/net/' + mesh_iface_b + '/libertas_mpp')
   commands.getoutput('echo 1 > /sys/class/net/' + mesh_iface_c + '/libertas_mpp')
   
   # Alias ANY_MPP_IP to any mesh interface
   commands.getoutput('ifconfig ' + mesh_iface_a + ':0 ' + ANY_MPP_IP)

   syslog.syslog( 'starting to serve MPPREQ replies' )
   # Start serving MPPREQ replies
   s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
   s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
   s.bind((host, port))

   while 1:
       try:
           message, address = s.recvfrom(8192)
           syslog.syslog( 'MPPREQUEST from:' + repr( address ) )
           subnet = address[0].split('.')[2]
           index = int(subnet) / 16
           if index == 1:
              s.sendto(mymessage_a, address)
           elif index == 2:
              s.sendto(mymessage_b, address)
           elif index == 3:
              s.sendto(mymessage_c, address)
           else:
              syslog.syslog( 'Ignoring non-local MPPREQUEST' )

       except (KeyboardInterrupt, SystemExit):
           raise
       except:
           traceback.print_exc()

Additional information may be found at Establishing a Mesh Portal.

DHCP

DHCP will be provided on all network segments except the one connected to the WAN.

Devices on the 'internal' network are assigned non-routable IP addresses, in the 172.18.x.x range.

# DHCP Server Configuration file.
#  see /usr/share/doc/dhcp*/dhcpd.conf.sample  
#
ddns-update-style interim;
#ignore client-updates;

option domain-name "open.net";
option domain-name-servers      172.18.0.1;
option ntp-servers              172.18.0.1;

subnet 172.18.0.0 netmask 255.255.240.0 {
       option routers                  172.18.0.1;
       option subnet-mask              255.255.240.0;
       option broadcast-address        172.18.15.255;
       range                           172.18.0.16 172.18.15.254;
#  As this subnet is wired, these lease times are on the long side
       default-lease-time      21600;
       max-lease-time          43200;
}

subnet 172.18.16.0 netmask 255.255.240.0 {
       option routers                  172.18.16.1;
       option subnet-mask              255.255.240.0;
       option broadcast-address        172.18.31.255;
       range                           172.18.16.16 172.18.31.254;
       default-lease-time      600;
       max-lease-time          1800;
}

subnet 172.18.32.0 netmask 255.255.240.0 {
       option routers                  172.18.32.1;
       option subnet-mask              255.255.240.0;
       option broadcast-address        172.18.47.255;
       range                           172.18.32.16 172.18.47.254;
       default-lease-time      600;
       max-lease-time          1800;
}

subnet 172.18.48.0 netmask 255.255.240.0 {
       option routers                  172.18.48.1;
       option subnet-mask              255.255.240.0;
       option broadcast-address        172.18.63.255;
       range                           172.18.48.16 172.18.63.254;
       default-lease-time      600;
       max-lease-time          1800;
}

The lease times on the laptops is kept low, as they may be moving between meshes.

The DHCP daemon is bound to the internal interfaces using /etc/sysconfig/dhcpd :

DHCPDARGS="eth1 msh0 msh1 msh2"


DNS

A local DNS server will be provided to cache common requests, in order to provide better network performance. It will also be used to provide a DNS entry for the schoolserver.

While it is possible to provide a DNS entry for each laptop, using explicit DHCP/DNS server integration, no software was prepared to utilize this and it is currently not supported.

One zone is supported for internal addresses. The name of this zone is currently being debated. Temporarily, it is being named 'open.net'.

The nameserver configuration file is:

// Named.conf file for the OLPC schoolserver
options
{
       query-source    port 53;
       query-source-v6 port 53;

       // Put files that named is allowed to write in the data/ directory:
       directory "/var/named"; // the default
       dump-file               "data/cache_dump.db";
       statistics-file         "data/named_stats.txt";
       memstatistics-file      "data/named_mem_stats.txt";

};
logging 
{
      channel default_debug {
               file "data/named.run";
               severity dynamic;
       };
};
view "localhost_resolver"
{
       match-clients           { localhost; };
       match-destinations      { localhost; };
       recursion yes;
       include "/var/named/named.root.hints";
       include "/var/named/named.rfc1912.zones";
       zone "open.net" in {
               type master;
               file "my.internal.zone.db";
               allow-update {127.0.0.1; };
       };
}; 
view "internal"
{
/* This view will contain zones you want to serve only to clients
  that connect directly to the attached LAN interfaces - "localnets" .
*/
       match-clients           { localnets; };
       match-destinations      { localnets; };
       recursion yes;
       include "/var/named/named.root.hints";
       zone "open.net" { 
               type master;
               file "my.internal.zone.db";
               allow-update {127.0.0.1; };
       };
       zone "0.18.172.in-addr.arpa" {
               type master;
               file "my.internal.zone.in-addr.db";
               allow-update {127.0.0.1; };
       };
       zone "16.18.172.in-addr.arpa" {
               type master;
               file "my.internal.zone.16.in-addr.db";
               allow-update {127.0.0.1; };
       };
       zone "32.18.172.in-addr.arpa" {
               type master;
               file "my.internal.zone.32.in-addr.db";
               allow-update {127.0.0.1; };
       };
       zone "48.18.172.in-addr.arpa" {
               type master;
               file "my.internal.zone.48.in-addr.db";
               allow-update {127.0.0.1; };
       };
};
key ddns_key
{
       algorithm hmac-md5;
       secret "********************************************************";
};


HTTP Cache

Squid 2.6 will be used for now.

Maintenance & Utility

The following services will be provided:

sshd

Used both for maintenance and as the transport for backups from the laptops.

rsync

Provided as a command line tool, not run as a daemon. Used for backups.

Updating

The School server software will be updated from an OLPC maintained repository, using yum, the package manager in Fedora. While this repository will probably be country/region specific, it currently resides in Cambridge, US.

An software update will be periodically triggered on the school server. Probably weekly ?

For managing the different needs (localisation, applications, configuration) we will either use FAI or slack (or rewrite a tool with similar functionality from scratch ;)

Laptop updates use a separate mechanism, which relies on the school server to provide the update files.

Monitoring

A method for monitoring the health of school servers deployed in the field is still under investigation.

  • Swatch was considered
  • Munin seems promising
  • CoMon is the starting point for what will eventually be deployed