not invented here

Friday, October 08, 2010

Remote Desktop on second monitor

I have a dual monitor (two 1600x1200 monitors) setup on my Ubuntu machine, and regularly have to connect to Windows machines with rdesktop. I would like the remote desktop to be full-screen on my second monitor, keeping my primary monitor open for other tasks. Here is the magic incantation to move the remote desktop to my second monitor:


/usr/bin/rdesktop -D -g 1600x1200+1600x0 somemachinename.dhcp

The '-D' parameter hides window manager decorations, allowing me to use the whole screen for the remote desktop, and '-g' specifies the + of the desktop.

And the result ...


Wednesday, April 29, 2009

Compacting subnets

Using the script in my previous post, I now have a list of subnets that are all local to South Africa. However, this list contains subnets within subnets and adjacent subnets, and since I am mainly interested in the fact that they are all local, I could compact this list quite a bit. The original subnet list contains almost 1500 routes.

root@slowpoke ~ $ wc -l < localnets.all
1494
root@slowpoke ~ $

After spending some time writing my own code to do the compacting, I found the Python netaddr library, that does it all for me. My script looks like this:

#! /usr/bin/python

import sys
import netaddr

nets = [netaddr.CIDR(line) for line in sys.stdin]
compacted_nets = netaddr.CIDR.summarize(nets)

for net in compacted_nets:
print net

And using it like this

root@slowpoke ~ $ ./merge < localnets.all > localnets
root@slowpoke ~ $

cuts the list of subnets by more than half

root@slowpoke ~ $ wc -l < localnets
708
root@slowpoke ~ $

Wednesday, April 22, 2009

South African subnets

I want to split my traffic over my two ADSL connection based on whether the destintation is local (to South Africa), or international. First of all, I need find out which networks are local to South Africa. Luckily, Internet Solutions provides a public server enabling me to do just that.


> telnet route-server.is.co.za

Trying 196.4.160.227...
Connected to route-server.is.co.za.
Escape character is '^]'.

##################### local-route-server.is.co.za #####################

This route server contains local South African routes from an
Internet Solution's customer view.

Please feel free to make use of the following commands for debuging:

ping
traceroute
show ip bgp
show ip bgp regexp

This router supports the cisco "| [begin,exclude,include]" command format

If you have any questions relating to this route-server please feel free
to send email to: peering@is.co.za

NOTE: Availability of this route-server is not guaranteed.

##################### local-route-server.is.co.za #####################

local-route-server line 67

local-route-server>

local-route-server> show ip bgp

BGP table version is 363647672, local router ID is 196.4.160.227
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal
Origin codes: i - IGP, e - EGP, ? - incomplete

Network Next Hop Metric LocPrf Weight Path
*> 17.255.248.0/23 168.209.255.8 0 3741 2686 i
*> 32.106.152.0/24 168.209.255.8 0 3741 2686 2686 ?
*> 32.106.153.0/24 168.209.255.8 0 3741 2686 ?
*> 32.107.9.0/24 168.209.255.8 0 3741 2686 i
*> 32.238.152.0/24 168.209.255.8 0 3741 2686 ?
*> 32.238.153.0/24 168.209.255.8 0 3741 2686 ?
*> 32.239.182.0/24 168.209.255.8 0 3741 2686 ?
*> 41.0.0.0/16 168.209.255.8 0 3741 5713 36994 i
*> 41.0.5.0/24 168.209.255.8 0 3741 5713 36994 ?
*> 41.0.16.0/21 168.209.255.8 0 3741 5713 36994 ?
*> 41.0.19.0/24 168.209.255.8 0 3741 5713 36994 ?
*> 41.0.20.0/24 168.209.255.8 0 3741 5713 36994 ?
*> 41.0.72.0/21 168.209.255.8 0 3741 5713 36994 ?
*> 41.0.196.0/24 168.209.255.8 0 3741 5713 36994 i
*> 41.0.208.0/22 168.209.255.8 0 3741 5713 36994 i
*> 41.0.236.0/24 168.209.255.8 0 3741 5713 36994 i
*> 41.0.248.0/24 168.209.255.8 0 3741 5713 36994 i
*> 41.1.0.0/18 168.209.255.8 0 3741 5713 36994 29975 i
--More--


What we are interested in, is the Network column. If we can extract all those entries, we have all the network subnets that are local to South Africa. So, let's automate the route extraction with the following getroutes.py script:


#! /usr/bin/python

import telnetlib
import re

def net_from_ip(ip):
"""Calculates the (implied) CIDR mask of an IP address, based on its class

Example:

>>> net_from_ip('41.100.0.0')
'8'
>>> net_from_ip('141.100.0.0')
'16'
>>> net_from_ip('241.100.0.0')
'24'
>>>
"""
# Split address into quads for easier testing ...
q = ip.split('.')
# Determine the mask from the class of the IP address ...
if int(q[0]) < 128:
# Leading bit 0xx, so class A ...
net = '8'
elif int(q[0]) < 192:
# Leading bits 10x, so class B ...
net = '16'
else:
# Only class C left ...
net = '24'
return net

def get_routes():
host = 'local-route-server.is.co.za'
prompt = 'local-route-server>'

session = telnetlib.Telnet(host)
session.read_until(prompt, 5) # Wait for prompt
session.write('terminal length 0\n')
session.read_until(prompt, 5) # Wait for prompt
session.write('show ip bgp\n')
bgp_routes = session.read_until(prompt) # Return all results until prompt
session.write('exit\n')

nets = []

for line in bgp_routes.split('\r\n'):
# The lines we are looking for looks something like this:
# *> 216.5.192.0/21 168.209.255.8 0 3741 2905 i
# We are interested in the second column ...
if line.startswith('*'):
subnet = line.split()[1]

temp = subnet.split('/')
ip = temp[0]
if len(temp) == 2:
mask = temp[1]
else:
mask = net_from_ip(ip)

nets.append("%s/%s" % (ip, mask))

return nets

if __name__ == "__main__":
routes = get_routes()
for i in routes:
print i

Monday, March 23, 2009

Routing over multiple PPP accounts (Part2)

I opted to handle the DNS servers of the two PPP connections manually. Configure each PPP connection to not add its DNS servers to the /etc/resolv.conf file, rather we will manually add the DNS server entries to /etc/resolv.conf later. Edit /etc/ppp/pppoe-is.conf, changing the lines DNS=SERVER and USEPEERDNS=yes to DNS=NOCHANGE and USEPEERDNS=no. Do the same for the other connection (/etc/ppp/pppoe-saix.conf). Now create /etc/resolv.conf with a list of all the DNS servers you want to use. This is my /etc/resolv.conf

root@slowpoke ~ $ cat /etc/resolv.conf
nameserver 168.210.2.2
nameserver 196.14.239.2
nameserver 196.43.45.190
nameserver 196.43.46.190
root@slowpoke ~ $

The next step is to route DNS queries specifically over the appropriate PPP connection. We will create a routing table for each PPP that will route packets intended for servers local to that connection over the right PPP connection. Edit /etc/iproute2/rt_tables to define the two new routing tables. This is mine

root@slowpoke ~ $ cat /etc/iproute2/rt_tables 
#
# reserved values
#
255 local
254 main
253 default
0 unspec
#
# local
#
#1 inr.ruhep
#
1 ppp0
2 ppp1
6 IS
7 SAIX
root@slowpoke ~ $

Now we will modify /etc/ppp/ip-up.d/ip-up.local.sh to read the connection-specific destinations (in this case, the connection's DNS servers) from a file and add them to the appropriate routing table. The problem is how to uniquely identify which connection (in my case IS or SAIX) is going up in the ip-up-local.sh script, so we can add the entries appropriate for that connection. The IS connection can be either ppp0 or ppp1, depending on whether it was brought up first or second. Luckily, we can edit the /etc/ppp/pppoe-is.conf file to provide us with that info; just edit the line that reads

PPPD_EXTRA=""
to read
PPPD_EXTRA="ipparam IS"
. This ensures that the the value "IS" will be pass as the 6th parameter to the /etc/ppp/ip-up.d/ip-up.local.sh script when the IS connection goes up. Similary, edit the line in /etc/ppp/pppoe-saix.conf to read
PPPD_EXTRA="ipparam SAIX"
. Note that I used the same names that I used in the rt_tables file. Now I can modify my /etc/ppp/ip-up.d/ip-up.local.sh script:

root@slowpoke ~ $ cat /etc/ppp/ip-up.d/ip-up.local.sh 
#!/bin/sh

INTERFACE=$1
IP=$4
GATEWAY=$5
PROVIDER=$6

# Create the entries in the dedicated routing table for this interface. It's basically the route
# to the gateway, as well as the default route. This routing table will be used for routing
# replies to incoming packets on this interface

/sbin/ip route add $GATEWAY dev $INTERFACE src $IP table $INTERFACE
/sbin/ip route add default via $GATEWAY table $INTERFACE

# Create the routing rule that uses the above routing table. When we already have the source
# address, route out over the above table

/sbin/ip rule add prio 1000 from $IP lookup $INTERFACE

# Add connection-specific routing entries ...

while read i; do /sbin/ip route add $i dev $INTERFACE table $PROVIDER; done < $PROVIDER

# ... and create the rule that uses this table.

/sbin/ip rule add prio 1500 from all lookup $PROVIDER

# Create the main default route ... will be overwritten when the second PPP connection goes up

/sbin/ip route add default dev $INTERFACE via $GATEWAY

I added some rules with specific priorities to make sure they are created in the right order. All that is needed now is to create the connection-specific files containing the DNS server entries. I created the files IS and SAIX in /etc/ppp/ip-up.d/

root@slowpoke ~ $ ls /etc/ppp/ip-up.d/   
30-wins.sh 50-initd.sh SAIX ip-up.local.sh
40-dns.sh IS
root@slowpoke ~ $ cat /etc/ppp/ip-up.d/IS
168.210.2.2
196.14.239.2
root@slowpoke ~ $ cat /etc/ppp/ip-up.d/SAIX
196.43.45.190
196.43.46.190
root@slowpoke ~ $

Sunday, March 22, 2009

Routing over multiple PPP accounts (Part1)

In my previous post, I have set up two PPPoE accounts. Now we will try to get basic routing to work. The first thing we want to do is to route replies of packets coming in over a specific interface, back out over that same interface. Perhaps the cleanest way to do this is to create a routing table for each PPP account. Edit /etc/iproute2/rt_tables to append the lines to create the ppp0 and ppp1 routing table entries, it should look something like

root@slowpoke ~ $ cat /etc/iproute2/rt_tables 
#
# reserved values
#
255 local
254 main
253 default
0 unspec
#
# local
#
#1 inr.ruhep
#
1 ppp0
2 ppp1

Now we want to create the routing rules for each of the interfaces, and we want to create them automatically whenever the interface goes up. We can do this by creating a bash script in the /etc/ppp/ip-up.d directory (mine is called ip-up.local.sh, the name is irrelevant, as long as it ends in ".sh"). Also remember to make the script executable. This script is called whenever a new interface goes up, with the following parameters (among others): the INTERFACE that just went up, the IP address of the interface, and the GATEWAY address of the interface. This is what my script looks like:

root@slowpoke ~ $ cat /etc/ppp/ip-up.d/ip-up.local.sh 
#!/bin/sh

INTERFACE=$1
IP=$4
GATEWAY=$5

# Create the entries in the dedicated routing table for this interface. It's basically the route
# to the gateway, as well as the default route. This routing table will be used for routing
# replies to incoming packets on this interface

/sbin/ip route add $GATEWAY dev $INTERFACE src $IP table $INTERFACE
/sbin/ip route add default via $GATEWAY table $INTERFACE

# Create the routing rule that uses the above routing table. When we already have the source
# address, route out over the above table

/sbin/ip rule add from $IP lookup $INTERFACE

# Create the main default route ... will be overwritten when the second PPP connection goes up

/sbin/ip route add default dev $INTERFACE via $GATEWAY

After establishing the two PPP connections, you should be able to access both IP addresses from the internet (outside). Replies to incoming packets will now be routed back over the same interface

Next step is to manage the DNS servers of the PPP links ...

Thursday, March 19, 2009

Multiple PPP accounts

I have two ADSL accounts, one for local (local to South Africa) traffic, and one for international traffic. For this to work, I need to get two simultaneous PPP accounts running.

First step ... install rp-pppoe:

root@slowpoke ~ # emerge rp-pppoe
.
.
.
* GNU info directory index is up-to-date.

To configure the first account, run

root@slowpoke ~ # pppoe-setup

and enter all the necessary details for this account. This will create a configuration file /etc/ppp/pppoe.conf. Before configuring the second account, copy this file out of harm's way

root@slowpoke ~ # cp /etc/ppp/pppoe.conf /etc/ppp/pppoe-is.conf

Now configure the second account by re-running pppoe-setup.

root@slowpoke ~ # pppoe-setup

and 'save' the resulting configuration file:

root@slowpoke ~ # cp /etc/ppp/pppoe.conf /etc/ppp/pppoe-saix.conf

Now we need to edit the configuration files for the two accounts so that we will be able to have both running at the same time. We do this by editing the line in the configuration files that read

PIDFILE="/var/run/rp-pppoe.pid"

to be unique for each file. In my case, the line reads

PIDFILE="/var/run/is-pppoe.pid"

and

PIDFILE="/var/run/saix-pppoe.pid"

respectively for the two configuration files. This allows me to start both connections at the same time without Gentoo complaining that the PPPoE connection is already up

root@slowpoke ~ # pppoe-start /etc/ppp/pppoe-is.conf
.. Connected!
root@slowpoke ~ # pppoe-start /etc/ppp/pppoe-saix.conf
.. Connected!

Further proof that both connections are up:

root@slowpoke ~ # ip link
1: lo: mtu 16436 qdisc noqueue
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:1e:58:39:f0:6c brd ff:ff:ff:ff:ff:ff
9: ppp0: mtu 1492 qdisc pfifo_fast qlen 3
link/ppp
10: ppp1: mtu 1492 qdisc pfifo_fast qlen 3
link/ppp
root@slowpoke ~ #

Of course, there are still other issues to sort out, namely routing and which connection's DNS servers to use, but I will leave that for later.

Sunday, March 15, 2009

Passwordless RSH on Gentoo

I have an old AMD K6-III box with 128MB memory that I use as my router, firewall and media server for my XBox. Everytime I have encoded DVDs that I want to load onto the server, I use rsync to update the contents. I noticed that it was slow, even on my 100 Mb/s LAN I could get no more than a 2 MB/s transfer rate. Checking the CPU usage, I noted that sshd was using about 75% cpu time, and rsync about 25%. It seemed that my network throughput was limited by the CPU bottleneck (due to the encryption overhead of SSH, I assume). Which is why I tried to get RSH up and running on it, to see what performance increase I could get with using rsh instead of ssh.

First, let's install rsh:
root@slowpoke ~ $ emerge netkit-rsh

Start up xinetd (since rshd is started by xinetd) ...

root@slowpoke ~ $ /etc/init.d/xinetd start
* Starting xinetd ... [ ok ]
root@slowpoke ~ $

Let's see if we can use rlogin on the same machine ...

somebody@slowpoke ~ $ rlogin localhost
localhost: Connection refused
somebody@slowpoke ~ $

So I can't rlogin, but running xinetd in debug mode shows why ...

root@slowpoke ~ $ /etc/init.d/xinetd stop
* Stopping xinetd ... [ ok ]
root@slowpoke ~ $ xinetd -d
.
.
.
.
09/3/16@14:23:00: CRITICAL: 6137 {init_services} no services. Exiting...
root@slowpoke ~ $

There are no services running, rlogin is disabled by default. Enable the rlogin service by editing /etc/xinetd.d/rlogin to look like the following (by changing 'disable = yes' to 'disable = no'):

service shell
{
socket_type = stream
protocol = tcp
wait = no
user = root
group = tty
server = /usr/sbin/in.rlogind
log_on_success = PID HOST USERID EXIT DURATION
log_on_failure = USERID ATTEMPT
disable = no
}

After restarting xinetd, we can successfully run rlogin ...

somebody@slowpoke ~ $ rlogin localhost
Password:
Last login: Mon Mar 16 14:25:00 SAST 2009 from localhost on pts/6
somebody@slowpoke ~ $

To prevent rlogin from asking for a password, we create a .rhosts file in the user's home folder, containing the hostname from which to allow passwordless logins:

somebody@slowpoke ~ $ echo localhost > .rhosts
somebody@slowpoke ~ $

Testing rlogin again:

somebody@slowpoke ~ $ rlogin localhost
Password:
Last login: Mon Mar 16 14:27:00 SAST 2009 from localhost on pts/6
somebody@slowpoke ~ $

So rlogin still prompts for a password, checking /var/log/messages shows the following error message:

Mar 16 14:27:00 slowpoke rlogind[6346]: PAM unable to dlopen(/lib/security/pam_rhosts_auth.so): /lib/security/pam_rhosts_auth.so: cannot open shared object file: No such file or directory

And sure enough, the file pam_rhosts_auth.so does not exist, although there is a file called pam_rhosts.so.

root@slowpoke ~ $ ls /lib/security/
pam_access.so pam_ftp.so pam_mkhomedir.so pam_succeed_if.so
pam_cracklib.so pam_group.so pam_motd.so pam_tally.so
pam_debug.so pam_issue.so pam_namespace.so pam_time.so
pam_deny.so pam_keyinit.so pam_nologin.so pam_umask.so
pam_echo.so pam_lastlog.so pam_permit.so pam_unix.so
pam_env.so pam_limits.so pam_rhosts.so pam_warn.so
pam_exec.so pam_listfile.so pam_rootok.so pam_wheel.so
pam_faildelay.so pam_localuser.so pam_securetty.so pam_xauth.so
pam_filter pam_loginuid.so pam_shells.so
pam_filter.so pam_mail.so pam_stress.so
root@slowpoke ~ $

According to the following bug report, the filename change was not captured in the corresponding configuration files. So we edit /etc/pam.d/rlogin to reflect the name change (by substituting pam_rhosts.so for pam_rhosts_auth.so):

#%PAM-1.0
# For root login to succeed here with pam_securetty, "rlogin" must be
# listed in /etc/securetty.
auth required pam_securetty.so
auth sufficient pam_rhosts.so
auth include system-remote-login
account include system-remote-login
password include system-remote-login
session include system-remote-login

And finally, success ...

somebody@slowpoke ~ $ rlogin localhost
Last login: Mon Mar 16 14:27:00 SAST 2009 from localhost on pts/6
somebody@slowpoke ~ $

Similarly, getting rsh to work, you need to enable the rshd service by editing /etc/xinetd.d/rsh to read:

service shell
{
socket_type = stream
protocol = tcp
wait = no
user = root
group = tty
server = /usr/sbin/in.rshd
log_on_success = PID HOST USERID EXIT DURATION
log_on_failure = USERID ATTEMPT
disable = no
}

and restart xinetd to activate the change. Also edit /etc/pam.d/rsh to use the rhosts.so module (remember the name change):

#%PAM-1.0
# For root login to succeed here with pam_securetty, "rsh" must be
# listed in /etc/securetty.
auth required pam_securetty.so

# Uncomment this and comment the following to use rhosts_auth module
auth required pam_rhosts.so
#auth include system-remote-login

account include system-remote-login
session include system-remote-login

Testing rsh ...

somebody@slowpoke ~ $ rsh localhost whoami
somebody
somebody@slowpoke ~ $

Next step was trying rsh from another machine on the local network:

somebody@grey-area ~ $ rsh slowpoke whoami
poll: protocol failure in circuit setup
somebody@grey-area ~ $

Editing /etc/xinetd.conf to enable xinetd services on your local network solved this problem. Change the line reading

only_from = 127.0.0.1

to

only_from = 127.0.0.1 192.168.1.0/24

by adding whatever subnet would be appropriate for your network. Restart xinetd for the change to take effect. To enable passwordless rsh from another machine on your local network involves adding the required host name to your .rhosts file ...

somebody@slowpoke ~ $ echo grey-area >> .rhosts
somebody@slowpoke ~ $

... and testing ...

somebody@grey-area ~ $ rsh slowpoke whoami
somebody
somebody@grey-area ~ $

So now that I have rsh set up, I can use rsync over rsh to synchronise my files, and now I get about 8 MB/s throughput.