Author

Christopher Marshall (christopherlmarshall@yahoo.com)

Raw Notes on IPv6

# some commands

# load the kernel module
insmod ipv6

# show ipv6 routes
route -A inet6

# ping a link local address residing somewhere on the LAN eth0 is connected to
# this works from one machine to another!
ping6 -I eth0 fe80::2e0:81ff:fe10:38cd

# restart sshd with ipv6 support (meaning you restart it after the kernel module is loaded), 
# then connect to ssh using ipv6.
# this also works!
/etc/rc.d/rc.sshd restart
ssh -6 -l user ::1

# this is what doesn't work.
ssh -6 -l user fe80::2e0:81ff:fe10:38cd
# from searching the internet, I gather one problem may be that fe80 is a link local address and,
# as such, you have to specify an interface to use with it.
# ssh may not let you specify an interface.
# so, perhaps, if you could create a global address, and put a route for it in your routing
# table, you could ssh from one machine to another.

# Ah HA!
# This lets me connect from one machine to another.
# on A:
ifconfig eth0 inet6 add 3ffe::1/64
# on B:
ifconfig eth0 inet6 add 3ffe::2/64
# on A:
ssh -6 -l user 3ffe::2
# that's because to use tcp or udp from one machine to another requires global addresses.
# link local addresses are only for machines to discover routes, I guess.
# I can't believe I got this working!!!

# commands and documents
# the main userspace command tool for manipulating tunnels, links, and routes. 
/sbin/ip
# this package contains the all important /sbin/ip command
/var/adm/packages/iproute2-2.6.7
# example of "ip link set" commands
   ip link set dev eth0 up
   ip link set dev eth0 down
   ip link set dev eth0 arp on
   ip link set dev eth0 arp off

   # this would change the name of the device, supposedly
   ip link set dev eth0 name eth1

   # change the link layer (mac) address
   ip link set dev eth0 address <lladdress>

   ip link set dev eth0 mtu <mtu>
   ip link set dev eth0 broadcast <lladdress>

   # This is described as changing the link layer peer address in the case of point-to-point links,
   # which makes no sense to me.  There is no link layer address in that case.
   ip link set dev eth0 peer <lladdress>

# example "ip link show" commands

   # show stats on eth0
   ip link show dev eth0

   # only show up interfaces
   ip link show up

# example "ip address add" commands

   # adds an ip address to eth0.  you can add a slash and prefix length if you want
   ip address add dev eth0 local <ip or ip6 address>

   # specifies the local and remote address on point to point links
   # If you specify a peer address, the local address can't have a prefix associated with it.
   # The prefix can only be associated with the peer.
   ip address add dev eth0 local <ip or ip6 address> peer <ip or ip6 address>

   # the label argument lets you tag an address with a name, like in ip-aliasing.
   ip address add dev eth0 local <ip or ip6 address> label eth0:0

   # the possible scope arguments are specified in /etc/iproute2/rt_scopes.
   # they are global, site, link, and host.
   ip address add dev eth0 local <ip or ip6 address> scope global

# "ip address delete" commands mirror "ip address add" commands

# example "ip address show" commands
   # show all addresses assigned to eth0
   ip address show dev eth0
   # only show addresses with the given scope
   ip address show scope <scope_val>
   # only show addresses matching the given prefix
   ip address show to <prefix>
   # only show addresses whose labels match the shell pattern
   ip address show label <pattern>
   # only list addresses installed due to stateless address configuration
   ip address show dynamic
   # only list addresses permanent addresses
   ip address show permanent
   # god only knows what these mean
   ip address show primary
   ip address show secondary

# "ip neigh" commands
# these are about the arp cache in ipv4 and the neighbor table in ipv6
   ip neigh add
   ip neigh change
   ip neigh replace
# and their arguments
   to     <neighbor ip or ip6 address>
   dev    <net dev>
   lladdr <lladdress>
   nud    <nud state>
# complete examples
   # we associate the mac de:ad:be:ef:ff:ff with the ipv6 address fe80::2e0:81ff:fe10:0000
   ip neigh add dev eth0 to fe80::2e0:81ff:fe10:0000 lladdr de:ad:be:ef:ff:ff
# more "ip neighbor" commands
   ip neigh delete
   ip neigh show
# and their arguments
   # prefix address selecting which neighbours to list
   to <address>
   # the network device
   dev <name>
   # only list neighbours which are not currently in use
   unused
   # god only knows what this means
   nud <nud state>
# complete commands
   # we remove the ipv6 to mac mapping for ipv6 address fe80::2e0:81ff:fe10:0000
   ip neighbour delete to fe80::2e0:81ff:fe10:0000

# "ip route" commands
   ip route add
   ip route change
   ip route replace
# route types
   unicast
   unreachable
   blackhole
   prohibit
   local
   broadcast
   throw
   nat
   anycast
   multicast
# arguments
   to <address/prefix>
   tos <tos>
   dsfield <tos>
   metric <number>
   preference <number>
   table <number or string from /etc/iproute2/rt_tables which includes main, local, and nat>
   dev <network dev>
   via <address or next hop router or, for NAT routes, the first address in the block of translated IP destinations>
   src <source address to prefer when sending to this destination>
   scope <scope value>
   # RTPROTO is one of redirect, kernel, boot, static, ra.
   protocol <RTPROTO>
   # this is a cute one.  IT takes its own subarguments: via, dev, and weight.  It is for
   # specifying mulipath routes that are switched between.  A form of load balancing, 
   # in a sense
   nexthop <NEXTHOP>

# more "ip route commands"
   # takes the same arguments as "ip route add"
   ip route delete

# more "ip route commands"
   # this will only show you ipv4 info, for some reason
   ip route show
   # this will show you ipv6 info
   ip -f inet6 route show
# arguments
   to
   tos
   table
   cloned
   cached
   from
   protocol
   scope
   type
   dev
   via
   src
   realm
   realms

# This command gets a single route to a destination and prints its contents as the kernel sees it.
ip route get to <address> from <address>

# a routing example using a ppp link
# on A
   ip address add dev ppp0 3ffe::1
   ip route add dev ppp0 3ffe::0/64
# on B   
   ip address add dev ppp0 3ffe::2
   ip route add dev ppp0 3ffe::0/64
   ping6 3ffe::1
   ssh -l user 3ffe::1

# I would have though this would work but it doesn't
# perhaps local and peer are ipv4 only concepts for pointtopoint links?
# on A
   ip address add dev ppp0 local 3ffe::1 peer 3ffe::2
# on B   
   ip address add dev ppp0 local 3ffe::2 peer 3ffe::1
   ping6 3ffe::1
   ssh -l user 3ffe::1
   
# ip tunnels
   # ip tunnel commands
   ip tunnel add
   ip tunnel change
   ip tunnel delete
   # arguments
   name <name of tunnel device>
   mode <ipip, sit, or gre>
   remote <address of remote endpoint>
   local <address of local tunnel endpoint.  must be an address of another interface of this host>
   ttl <N>
   tos T
   dsfield T
   dev <name of net dev to force tunneled packets to traverse to prevent escape when endpoint changes>
   nopmtudisc
   key <key to use for GRE tunnels in both directions>
   ikey <key to use for GRE tunnels for input packets>
   okey (key to use for GRE tunnels for output packets>
   csum, icsum, ocsum
   seq,iseq,oseq
   # this command lists tunnels
   ip tunnel show

# experiments

# GRE ip6 on ip4 tunnel
# I wasn't able to get an ip6 on ip6 tunnel going
# the ip route commands don't seem to be necessary.
# they are implied by the preifx length in the address assigned to the interface
# I mismatched the keys to see if it would prevent communication and it did.
# the key has to be either a number or an ip address-like dotted quad.  Does that mean
# only 32 bit keys?  Isn't that awful?
   A:
   ip address add dev eth0 3ffe::1/64
   ping6 3ffe::2
   modprobe ip_gre
   ip tunnel add tun1 mode gre dev eth0 key 1234567890 local 12.26.73.160 remote 12.26.73.158
   ip link set tun1 up
   ip address add dev tun1 3ffd::1/64
   ip route add dev tun1 3ffd::/64
   ip route show table all
   ip link set tun1 down
   ip tunnel del tun1
   B:
   ip address add dev eth0 3ffe::2/64
   ping6 3ffe::1
   modprobe ip_gre
   ip tunnel add tun1 mode gre dev eth0 key 1234567890 remote 12.26.73.160 local 12.26.73.158
   ip link set tun1 up
   ip address add dev tun1 3ffd::2/64
   ip route add dev tun1 3ffd::/64
   ip route show table all
   ip link set tun1 down
   ip tunnel del tun1

# ipv4 compatible ipv6 addresses
# these are used to carry ipv6 packets over an ipv4-only routing infrastructure
# with automatic tunneling.
# the address format it ::a.b.c.d/96, where a.b.c.d is the ipv4 address a dual stack node
# has as far as the ipv4 routing infrastructure is concerned.
# you enable this by adding the route ::/96 to whatever link connects you to the ipv4 network.
   A:
      ip address add ::10.0.0.1 dev eth0
      ip route add ::/96 dev eth0
   B:
      ip address add ::10.0.0.2 dev eth0
      ip route add ::/96 dev eth0
   A:
      ping6 ::10.0.0.2
# after you have set this up, you will notice a GRE tunnel device has been created
# to handle it.
# I've tested this between two IP6 hosts on an ethernet, but that is not much of a test.
# I think you would need a minimum of three machines with two lan segments to test this
# fully (A6-B4-C4-D6), and you would have to prevent B4 and C4 from talking ip6 to each other
# (I believe you could do that by deleting ip6 addresses from the appropriate B4->C4 and C4->B4 links).
# You would ping6 from A to D, and by running tcpdump on B-C you would see ipv4 packets carrying the icmp6
# packets.

# ipsec

# setkey
# the main ipsec userspace tool
# manipulates the SAD (secutiry association database) and the SPD
# (security policy database)

# dump the SAD entries
setkey -D 
# dump the SPD entries
setkey -D -P
# flush SAD entrie
setkey -F
# flush SPD entries
setkey -F -P


# the following two scripts show how to encrypt all traffic between 12.26.73.160 and
# 12.26.73.45
# this script is run on 12.26.73.160:
   #!/bin/bash
   # ipsec-ex-1.sh
   key="5eda6794e8a9bd89491bec9dc66b52da"
   modprobe ah4
   modprobe ah6
   modprobe esp4
   modprobe esp6
   (
      echo "flush;"
      echo "spdflush;"

      # security associations
      echo "add 12.26.73.160 12.26.73.45 esp 20000 -E rijndael-cbc 0x${key} ;"
      echo "add 12.26.73.45 12.26.73.160 esp 20001 -E rijndael-cbc 0x${key} ;"

      # security policies
      echo "spdadd 12.26.73.160 12.26.73.45 any -P out ipsec"
      echo "   esp/transport//require;"
      echo "spdadd 12.26.73.45 12.26.73.160 any -P in ipsec"
      echo "   esp/transport//require;"
   ) | setkey -c
# and this one on 12.26.73.45:
   #!/bin/bash
   # ipsec-ex-2.sh
   key="5eda6794e8a9bd89491bec9dc66b52da"
   modprobe ah4
   modprobe ah6
   modprobe esp4
   modprobe esp6
   (
      echo "flush;"
      echo "spdflush;"

      # security associations
      echo "add 12.26.73.160 12.26.73.45 esp 20000 -E rijndael-cbc 0x${key} ;"
      echo "add 12.26.73.45 12.26.73.160 esp 20001 -E rijndael-cbc 0x${key} ;"

      # security policies
      echo "spdadd 12.26.73.160 12.26.73.45 any -P out ipsec"
      echo "   esp/transport//require;"
      echo "spdadd 12.26.73.45 12.26.73.160 any -P in ipsec"
      echo "   esp/transport//require;"
   ) | setkey -c
# policies, unlike associations, can use address ranges in 
# "address/prefix" notation, so you could write
# a single script to run on both like this:
   #!/bin/bash
   # ipsec-ex-3.sh
   key="5eda6794e8a9bd89491bec9dc66b52da"
   modprobe ah4
   modprobe ah6
   modprobe esp4
   modprobe esp6
   (
      echo "flush;"
      echo "spdflush;"

      # security associations
      echo "add 12.26.73.45 12.26.73.160 esp 20000 -E rijndael-cbc 0x${key} ;"
      echo "add 12.26.73.160 12.26.73.45 esp 20001 -E rijndael-cbc 0x${key} ;"

      # security policies
      echo "spdadd 12.26.73.0/24 12.26.73.0/24 any -P out ipsec"
      echo "   esp/transport//require;"
      echo "spdadd 12.26.73.0/24 12.26.73.0/24 any -P in ipsec"
      echo "   esp/transport//require;"
   ) | setkey -c

# radvd
# radvd is the ipv6 router advertisement daemon
#
# The simplest thing you can do is advertise a prefix on a link and have nodes 
# global addresses from it.  The references I looked up said you should use an 80
# bit prefix for global address autoconfiguration because the address would be 
# composed of the prefix and the 48 bit ethernet mac address.  When I tried this,
# however, I noticed a syslog message on the client host like this:
ADDRCONF: prefix with wrong length 80

# I looked at the kernel code in ipv6/addrconf.c and noticed that it would only accept
# 64 bit prefixes for address autoconfiguration.  I then noticed an RFC on ipv6 privacy
# concerns (I forget the number) and it talked about how embedding the 48 bit ethernet address
# in a globally unique address was bad for privacy and this had been changed to the 64 bit
# prefix scheme.

# 
# after copying this to /etc/radvd.conf :
interface eth0 {
   AdvSendAdvert on;
   prefix 5f15:9100:c2dd:1400::0/64
   {
      AdvOnLink on;
      AdvAutonmous on;
   };
};

# before starting radvd, you enable forwarding with
echo "1" > /proc/sys/net/ipv6/conf/all/forwarding

# you can start radvd like this
radvd -d 4 -m stderr

# which will set the debug level to 4 (the highest) and write debug statements to stderr 
# instead of to syslog.
# I've noticed that radvd doesn't automatically put itself in the background.  In a 
# startup script it would have to be started like this, which is unusual:
radvd &

hopeless_linux: RawNotes/ipv6 (last modified 2007-07-01 16:01:00)