Archive for the ‘linux’ Category

Recently in the Terragraph project I work on we changed from RPM to OPKG to removes some dependencies (e.g. perl) and make our overall image size smaller. I've never driven OPKG, but know RPM, so I made this cheat sheet for my shit memory.

I'm cheap so I don't have a Table plugin - So used Python to generate me one ūü§†

+--------------------------+-------------------------------+
| RPM Cmd                  | OPKG Cmd                      |
+--------------------------+-------------------------------+
| rpm -qa                  | opkg list-installed           |
| rpm -qf <FILE>           | opkg search <FILE>            |
| rpm -i[vh] --force <PKG> | opkg install [--force*] <PKG> |
| rpm -e --force <PKG>     | opkg remove [--force*] <PKG>  |
+--------------------------+-------------------------------+
- opkg Force Examples:
  --force-depends|--force-downgrade|--force-remove

Recently a teammate and I have come across a frame forwarding issue with ECMP on a hardware ASIC in a device I work on where the use of Flow labels are used in the ECMP hash. This was interesting as we found iperf was not setting the Flow label at all, unless you specify the -L option and due to this we saw TCP traffic taking different paths, contradictory to what we thought we had configured in our FIB and what we actually wanted.

This sparked interest in me then wondering how popular platforms set the IPv6 Flow label for the different protocols; that being, ICMPv6, TCP and UDP. The Flow label being at Layer 3, I would expect it used the same for each protocol, but I could not find literature to back this theory up. So I fired up Wireshark on Mac, Linux and Windows to find out what they do. Here are my results I found.

If you want to know more about what Flow Labels are I would reccomened the following links:

  • Wikipedia:¬†https://en.wikipedia.org/wiki/IPv6_packet#Fixed_header
  • RFC:¬†https://tools.ietf.org/html/rfc6437

Summary

With each protocol the client and the server maintained consistent Flow labels for the 'session' as expected, except for Windows with ICMPv6 Requests! Here Windows set the Flow label to 0 (0x00000000).

Tests Performed

To get my results I ran:

  • ping6 -c 2 us.cooperlees.com
    (ICMPv6)
    - ping -6 us.cooperlees.com on Windows
  • ssh -6 us.cooperlees.com
    (TCP)
    - Used putty on Windows
  • Raw NTP UDP Query
    Python 3 Code: https://pastebin.com/RDBRqG0G
    (UDP)

Linux

Test Distro: Ubuntu 18.04
Test Kernel: 4.15.0-23-generic

ICMPv6
- Different Flow label, but consistent for the 2 ping packets on each ICMPv6 Type 128/129 packet from sender and receiver

TCP
- Different Flow label for sender and receiver but consistent across the SSH connection.

UDP
- Different Flow label for sender and receiver for each UDP packet as expected.

Mac OS X

Test Version: 10.13.6 17G65
Test Kernel: Darwin Kernel Version 17.7.0

ICMPv6
- Different Flow label, but consistent for the 2 ping packets on each ICMPv6 Type 128/129 packet from sender and receiver

TCP
- Different Flow label for sender and receiver but consistent across the SSH connection.

UDP
- Different Flow label for sender and receiver for each UDP packet as expected.

Windows

Test Version: Microsoft Windows [Version 10.0.16299.371]

ICMPv6
- Windows sets the ICMPv6 Type 128 (request) IPv6 Flow label to 0x00000000!
(I also noticed different DSCP for traffic class)

TCP
- Different Flow label for sender and receiver but consistent across the SSH connection.

UDP
- Different Flow label for sender and receiver for each UDP packet as expected.

It took me far to long to find out how to config this, so I'm sharing it to be more searching on the Internets.

Scenario:

- NXOS BGP 'upsteam' / 'north bound' peer sharing the default route only
- Linux box runs Quagga sharing it's /56 routable behind it

Nexus Conf

feature bgp

router bgp 65170
  router-id 69.69.69.70
  address-family ipv6 unicast
    network 0::/0
  neighbor 69::69 remote-as 65169
    address-family ipv6 unicast

 

Quagga Conf

bgp.conf:

router bgp 65169
 bgp router-id 69.69.69.69

 neighbor 69::1 remote-as 65170

 address-family ipv6 unicast
  network 2400:0000:0000:6900::/56

 neighbor 69::1 activate

log file /var/log/bgpd.log
log stdout

So, every now and then on a PR I need to rebase and fix things so I can retest etc. - I always forget this so blogging it to remember.

Scenario:

I have a diff on origin/master on my forked repo and I need a rebase from upstream/master (where I forked from).

Process:
Github recommends merging (https://help.github.com/articles/syncing-a-fork/), this is not always the best way. I do the following:

  1. git remote add upstream https://github.com/python/cpython.git
  2. git fetch upstream master
  3. git rebase upstream/master (no space here '/' instead)

I hope this saves you some time as I continually waste time here.

Recently @ Facebook we found that we required IPv6 access to TACACS for auth (AAA) for the majority of our production Network Equipment. Tacacs+ (tac_plus) is an old daemon released by Cisco in the late 90s. It still works (even at our scale) and the config was doing what we required, so it was decided that we should add IPv6 Support to it to move forwards until we no longer require TACACS for authentication, authorization and accounting.

IPv6 has been added in true dirty 90s C code style via pre-processor macros. The source is publicly available via a GitHub Repository.

This version is based off F4.0.4.19 with the following patches (full history can be seen in the Git Repository):

  • Logging modifications
  • PAM Support
  • MD5 support
  • IPv6 (AF_INET6)¬†Socket Listening

Readme.md has most of the information you require to build the software and I have included RPM .spec files (that have been tested on CentOS 6). The specs generate two RPMS with tacacs+6 relying on the tacacs+ rpm to be installed for libraries and man pages.

RPMS Build on CentOS 6.5 x86_64 + SRC rpms avaliable here: http://cooperlees.com/rpms/

Usage Tips:

  • Do not add listen directives into tac_plus.conf so that each daemon can load the same conf file (for consistency)
  • Logging:
    • /var/log/tac_plus.acct and¬†tac_plus6.acct are where accounting information will go (as well as syslog) - Logrotate time ...
    • /var/log/tac_plus.log and¬†tac_plus6.log is where default debug logs will go
  • Configure syslog to send the¬†LOG_LOCAL3 somewhere useful (this will get both tac_plus and tac_plus6 log information)
  • Pid Files will live in /var/run/tac_plus.pid.0.0.0.0 and¬†tac_plus6.pid.::
  • The RPM does not /sbin/chkconfig --add or enable, so be sure to enable the version of tac_plus you require.

Tested Support on Vendor Hardware

  • Arista EoS (4.13.3F): need to use 'ipv6 host name ::1' as TACACS conf can't handle raw IPv6 addresses (lame)¬†
  • Cisco NXOS (6.0(2)U2(4) [build 6.0(2)U2(3.6)]):
    feature tacacs+
    tacacs-server key 7 "c00p3rIstheMan"
    tacacs-server host a:cafe::1
    tacacs-server host b:b00c::2
    aaa group server tacacs+ TACACS
    server a:cafe::1
    server b:b00c::2
    source-interface Vlan2001 (ensure what IP request will come from)
  • Juniper: >= Junos¬†13.3R2.7 required for IPv6 Tacacs (Tested on MX)

I know it's old school code but please feel free to submit bug patches / enhancements. This should allow us to keep this beast running until we can deprecate it's need ...

Recently I was required to do a network performance test between a Head Office and a WAN site. I knocked up this quick python script to parse the data collect to see the results. Thought it could be handy for others so here it is to download / share.

Download Script

Sample Output:

[plain]
cooper@dfbit:~/scripts/iperf-parse$ ./iperf-summary.py
------------------------------------
-- IPERF CSV Summariser --
-- Cooper Lees <me@cooperlees.com --
------------------------------------
-- SUMMARY --
- 20111212103043 to 20120103090052
- 1004 runs of IPERF
- Averages:
- Average Sent = 2.64M
- Average Received = 2.28M
- Average Send Bandwidth = 985.75K
- Average Receive Bandwidth = 805.12K
- Max Send Bandwidth = 1.08M (at 20111230183021)
- Max Receive Bandwidth = 837.16K (at 20120102113052)
------------------------------------
[/plain]

Code:

[python]
#!/usr/bin/python

# date,sender-ip,sender-port,receiver-ip,receiver-port,id,interval,transfer,bandwidth
# 20111212103043,10.120.15.8,45020,10.120.13.120,5001,5,0.0-21.4,2490368,931080
# 20111212103109,10.120.15.8,5001,10.120.13.120,57022,4,0.0-24.2,2228224,736145

FILENAME = 'client-iperf.log'

RUNS = 1

MAX_BANDWIDTH_SENT = 0
MAX_BANDWIDTH_SENT_DATE = 0
MAX_BANDWIDTH_RECEIVED = 0
MAX_BANDWIDTH_RECEIVED_DATE = 0

TOTAL_BANDWIDTH_SENT = 0
TOTAL_BANDWIDTH_RECEIVED = 0

TOTAL_SENT = 0
TOTAL_RECEIVED = 0

def convert_bytes(bytes):
bytes = float(bytes)
if bytes >= 1099511627776:
terabytes = bytes / 1099511627776
size = '%.2fT' % terabytes
elif bytes >= 1073741824:
gigabytes = bytes / 1073741824
size = '%.2fG' % gigabytes
elif bytes >= 1048576:
megabytes = bytes / 1048576
size = '%.2fM' % megabytes
elif bytes >= 1024:
kilobytes = bytes / 1024
size = '%.2fK' % kilobytes
else:
size = '%.2fb' % bytes
return size

f = open(FILENAME)
l1 = f.readline().strip().split(',')
l2 = f.readline().strip().split(',')
while l2 and l2[0] != '':
if RUNS == 1:
START = l1[0]

BW_SENT = int(l1[8])
BW_RECEIVED = int(l2[8])

TOTAL_SENT = TOTAL_SENT + int(l1[7])
TOTAL_RECEIVED = TOTAL_RECEIVED + int(l2[7])

TOTAL_BANDWIDTH_SENT = TOTAL_BANDWIDTH_SENT + int(l1[8])
TOTAL_BANDWIDTH_RECEIVED = TOTAL_BANDWIDTH_RECEIVED + int(l2[8])

if BW_SENT > MAX_BANDWIDTH_SENT:
MAX_BANDWIDTH_SENT = BW_SENT
MAX_BANDWIDTH_SENT_DATE = l1[0]

if BW_RECEIVED > MAX_BANDWIDTH_RECEIVED:
MAX_BANDWIDTH_RECEIVED = BW_RECEIVED
MAX_BANDWIDTH_RECEIVED_DATE = l2[0]

END = l2[0]
RUNS = RUNS + 1
l1 = f.readline().strip().split(',')
l2 = f.readline().strip().split(',')

f.close()

print "------------------------------------"
print " -- IPERF CSV Summariser -- "
print "-- Cooper Lees <me@cooperlees.com --"
print "------------------------------------"
print "-- SUMMARY --"
print "- %s to %s" % ( START, END )
print "- %d runs of IPERF" % RUNS
print "- Averages:"
print "-tAverage Sentttt= %s" % convert_bytes((TOTAL_SENT / RUNS))
print "-tAverage Receivedtt= %s" % convert_bytes((TOTAL_RECEIVED / RUNS))
print "-tAverage Send Bandwidthtt= %s" % convert_bytes((TOTAL_BANDWIDTH_SENT / RUNS))
print "-tAverage Receive Bandwidtht= %s" % convert_bytes((TOTAL_BANDWIDTH_RECEIVED / RUNS))
print "-tMax Send Bandwidthtt= %s (at %s)" % (convert_bytes((MAX_BANDWIDTH_SENT)), MAX_BANDWIDTH_SENT_DATE)
print "-tMax Receive Bandwidthtt= %s (at %s)" % (convert_bytes((MAX_BANDWIDTH_RECEIVED)), MAX_BANDWIDTH_RECEIVED_DATE)
print "------------------------------------"
[/python]

Cron Job Script to Collect Data:

[bash]
#!/bin/bash

SERVER="x.x.x.x"
LOG="client-iperf.log"
TIME="5"

echo "--> Starting iperf client @ $(date) ..." | tee -a $LOG

if [ "$1" == "-v" ]; then
iperf -t $TIME -c $SERVER -r -y C | tee -a $LOG
else
iperf -t $TIME -c $SERVER -r -y C >> $LOG
fi

echo "--> Finished iperf client @ $(date)" | tee -a $LOG
[/bash]

The inventor of the C programming language and integral part of UNIX development has past away. RIP Dennis Ritchie.


Thanks for the Uni lectures ...

BoingBoing Article

So I thought I would share a good IPTables starting template, all tested on Ubuntu 10.10.

[plain]

# Cooper Lees IPTables Rules
# Last Updated 20110409

# Drop by default
iptables -P INPUT DROP
iptables -A INPUT -i lo -j ACCEPT
#ICMP is Good
iptables -A INPUT -p icmp -j ACCEPT
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
# Only allow 4 new SSH connection per minute from a certain IP address
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --second 60 --hitcount 4 -j DROP
iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
# Handy if you have a IPv4 to IPv6 Tunnel ...
iptables -A INPUT -p 41 -s ${IPv4-Tunnel-Address} -j ACCEPT
# Handy for debuging what is getting blocked ...
iptables -A INPUT -j LOG --log-level debug --log-prefix "iptables INPUT: "
iptables -A INPUT -j REJECT --reject-with icmp-host-prohibited

[/plain]
- Load from CLI then use iptables-save > /etc/iptables.up.rules
- In Ubuntu add to /etc/network/interfaces "pre-up iptables-restore < /etc/iptables.up.rules" on to the loopback interface

Just thought I would pass on that my Ubuntu Iphone teathersing Shell Script has passed 1000 downloads.
Feels good to have people all over the world use your script ūüôā

Hope everyone that has downloaded it has enjoyed it as much as I have in the car on the way to work.

The iPhone in Tethering Mode

The iPhone in 'Tethering Mode'

To see my super high tech counter visit:
http://us.cooperlees.com/ to see the current count ūüôā

If you would like to use your iPhone 3.0 with your bluetooth capable Ubuntu 9.04 PC then uit.sh (Ubuntu Iphone Thethering) is for you. This script installs all required conf, allows you to enable and disable your iphone tethering and even uninstall the conf if you no longer need it. I do expect NetworkManager to eventually support this out of the box.

Thanks to http://xn--9bi.net/2009/06/17/tether...o-ubuntu-9-04/ blog post which assisted me in knowning what configuration was needed.

Usage:
-- Ubuntu iPhone Tethering (uit) Version 0.1 - Cooper Lees <me@cooperlees.com> --
Usage: ./uit.sh options
- This script will install, uninstall, enable and disable iPhone tethering with iPhone 3.0 Software.
- It has been tested on a upto date (patched) box as of 20090623.
- !! Be careful, this script will ask for your password to get root privledges to your system!

OPTIONS:
-h Show this message
-i Install required configuration
-u Uninstall required configuration
-c Connect Tethering
-d Disconnect Tethering
-m [] Set iPhone's MAC Address (to /home/USERNAME/.uitrc)
-v Verbose

Install Guide:
Avaliable from: http://us.cooperlees.com/download.php?F=uit.sh.gz

- Inital installation requires an active Internet Connection to get required dependancies through apt-get. Current dependancies = 'bluez-compat'
- Only the install requires you to sudo the script, other areas apropriately sudo where required.

Install Process:

  1. Open terminal
  2. wget http://us.cooperlees.com/download.php?F=uit.sh.gz
  3. gunzip uit.sh.gz
  4. chmod 755 uit.sh
  5. [OPTIONAL] Move the script into your sbin - 'sudo mv uit.sh /usr/sbin' (This will allow it to be in your PATH)
  6. Run 'sudo uit.sh -i' (You will need to have your iphone in discoverable mode with Bluetooth on)
  7. You will be notified if it all sucessfully installs.

Connect Process:
- Ensure Bluetooth is on and paired with your system (use the GNOME Bluetooth tool to pair). Also make sure Internet Tethering is on.

  1. uit.sh -c

- Once connected you will see the iPhone come up with a blue bar stating 'Internet Tethering' is activated.

Disconnect Process:
One command will disconnect from the iphone tethering - You should see the blue notification text dissapear.

  1. uit.sh -d

Uninstall Process:

  1. uit.sh -u

- This will remove conf from files and also make backup of files modified.

Hope you enjoy it as much as I am. Finding the bluetooth a little slow. But still very handy and good. Thanks Apple.