ここでは、IPv6をNGN経由のPPPoE接続により提供するプロバイダにLinuxにより接続する方法をメモします。
- 対象のOSはCentOS5.8です。
- インストール時にPPPoEを含む各種のパッケージはすでにインストールされているものとします。
特に必要なパッケージは
radvd(radvd-0.9.1-4)
dhcpv6(dhcpv6-1.0.10-20.el5)
rp-pppoe(rp-pppoe-3.5-32.1)
chkconfig(chkconfig-1.3.30.2-2.el5)
perl(perl関連パッケージ)
gccおよびKernelヘッダ、ライブラリ群(Wide版dhcpv6のコンパイルに必要)
です。- インタフェースeth0を使用してPPPoEを張ると共に、ローカルのNWに接続されているものとします。
CentOS5では、DHCPv6のパッケージとしてDHCP6cが用意されていますが、Prefix Delegationに対応していないため、WIDE版のDHCPv6パッケージを導入します。
# cd /usr/local # mkdir dhcpv6 # wget "http://sourceforge.jp/frs/g_redir.php?m=jaist&f=%2Fwide-dhcpv6%2Fwide-dhcpv6 %2Fwide-dhcpv6-20080615%2Fwide-dhcpv6-20080615.tar.gz" --201x-xx-xx 09:16:13-- http://sourceforge.jp/frs/g_redir.php?m=jaist&f=%2Fwide-dhcpv6 %2Fwide-dhcpv6%2Fwide-dhcpv6-20080615%2Fwide-dhcpv6-20080615.tar.gz sourceforge.jp をDNSに問いあわせています... xxx.xxx.xxx.xxx sourceforge.jp|xxx.xxx.xxx.xxx|:80 に接続しています... 接続しました。 HTTP による接続要求を送信しました、応答を待っています... 302 Found 場所: http://jaist.dl.sourceforge.net/project/wide-dhcpv6/wide-dhcpv6/wide-dhcpv6-20080615/ wide-dhcpv6-20080615.tar.gz --20xx-x-02 09:16:13-- http://jaist.dl.sourceforge.net/project/wide-dhcpv6/wide-dhcpv6/ wide-dhcpv6-20080615/wide-dhcpv6-20080615.tar.gz jaist.dl.sourceforge.net をDNSに問いあわせています... xxx.xxx.xxx.xxx, xxxx:xxxx:xxxx:xxxx::xxxx jaist.dl.sourceforge.net|xxx.xxx.xxx.xxx|:80 に接続しています... 接続しました。 HTTP による接続要求を送信しました、応答を待っています... 200 OK 長さ: 215354 (210K) [application/x-gzip] `wide-dhcpv6-20080615.tar.gz' に保存中 100%[================================================>] 215,354 --.-K/s 時間 0.08s 20xx-xx-xx 09:16:13 (2.64 MB/s) - `wide-dhcpv6-20080615.tar.gz' へ保存完了 [215354/215354] #
# tar zxvf wide-dhcpv6-20080615.tar.gz wide-dhcpv6-20080615 wide-dhcpv6-20080615/addrconf.c wide-dhcpv6-20080615/addrconf.h .....(省略)..... wide-dhcpv6-20080615/missing/getifaddrs.c wide-dhcpv6-20080615/missing/sys wide-dhcpv6-20080615/missing/sys/queue.h #
# cd dhcpv6 # ./configure checking for a BSD-compatible install... /usr/bin/install -c checking whether make sets $(MAKE)... yes checking for gcc... gcc .....(省略)..... checking for stdarg.h... yes configure: creating ./config.status config.status: creating Makefile # make gcc -g -O2 -I. -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=(以下省略) .....(省略)..... gcc -o dhcp6ctl dhcp6_ctlclient.o base64.o auth.o strlcpy.o strlcat.o arc4random.o -lfl #
# ln -s /usr/local/dhcpv6/wide-dhcpv6-20080615/dhcp6c /usr/local/dhcpv6/dhcp6c
# openssl rand -base64 16 > /usr/local/etc/dhcp6cctlkey既存のCentOSディストリビューションに含まれるdhcp6バイナリ群との競合/上書きを避けるため、make install は実行しません。
起動スクリプトで使用するIPv6アドレスフォーマット変換のPerlスクリプトを設定します。
ファイルは /opt/ipv6_tools/ipv6_conv として作成します。作成後、実行可能なようにモードを a+x で変更してください。
#!/usr/bin/perl -w ####################################################################################### # IPv6 address format converter # # File Name: # ipv6_conv # # Descriptions: # ipv6_conv converts standard ipv6 address nortation to non zero suppress notation # # option -r/--reverse: print reverse format for DNS # option -a/--all: print non zero suppress notation and reverse format # # History(Change log): # Version 1.0.0 2011.12.29 jj1req@ca.mbn.or.jp # first appeared # # CURRENT_VERSION="1.0.0" # # Copyright (c) 2011 Kazuhiro WATANABE ####################################################################################### use strict; use Getopt::Long; # get commandline options #================================================================== # subroutines #================================================================== #****************************************************************** # convert standard ipv6 address notation to non zero suppress notation #****************************************************************** sub expand_ipv6( $ ) { my @address; my @hex_adr; my $ipv6 = $_[0]; if( $ipv6 =~ m/::/ ) { # expand the short form expression to long form. my ( $adr_a, $adr_b ) = split( /::/, $ipv6 ); my @adr_a = split( /:/, $adr_a ); my @adr_b = split( /:/, $adr_b ); for (scalar @adr_a .. 7 - scalar @adr_b) { push( @adr_a, 0 ); } @address = (@adr_a, @adr_b); } else { @address = split( /:/, $ipv6 ); } return( @address ); } #****************************************************************** # non option #****************************************************************** sub conv_nonzero( $ ) { my @address = &expand_ipv6( $_[0] ); my $ipv6 = sprintf( "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", hex($address[0]), hex($address[1]), hex($address[2]), hex($address[3]), hex($address[4]), hex($address[5]), hex($address[6]), hex($address[7]) ); return( $ipv6 ); } #****************************************************************** # reverse option #****************************************************************** sub conv_reverse( $ ) { my @address = &expand_ipv6( $_[0] ); my $ipv6 = sprintf( "%04x%04x%04x%04x%04x%04x%04x%04x", hex($address[0]), hex($address[1]), hex($address[2]), hex($address[3]), hex($address[4]), hex($address[5]), hex($address[6]), hex($address[7]) ); my $i; my $str; my $rev = substr( $ipv6, 31, 1 ); for( $i=30; $i>=0; $i-- ) { $str = substr( $ipv6, $i, 1 ); $rev = join( ".", $rev, $str ); } return( $rev ); } #================================================================== # Main #================================================================== my $opt_rev = 0; my $opt_all = 0; my $ipv6; GetOptions( 'reverse' => \$opt_rev, 'all' => \$opt_all ); if( @ARGV != 1 ) { $ipv6 = <STDIN>; chomp( $ipv6 ); } else { $ipv6 = $ARGV[0]; } unless( $ipv6 =~ /^[0-9a-fA-F:]+$/ ) { print( " Error! argument includes unrecognized character: " . $ipv6 . "\n" ); exit(1); } if( $opt_all == 1 ) { print( &conv_nonzero( $ipv6 ) . "\n" ); print( &conv_reverse( $ipv6 ) . "\n" ); exit(0); } if( $opt_rev == 1 ) { print( &conv_reverse( $ipv6 ) . "\n" ); } else { print( &conv_nonzero( $ipv6 ) . "\n" ); } exit(0); #****************************************************************** # End of code. #******************************************************************
次に導入したWIDE版DHCP6cに対する設定を行います。
対象のコンフィグファイルは /etc/dhcp6c.conf です。
# # /etc/dhcp6c.conf # interface ppp0 { send ia-pd 0; }; id-assoc pd 0{ prefix-interface eth0 { sla-id 1; sla-len 0; }; };
PPPoEの設定を行います。PPPoEへの接続情報はあらかじめプロバイダからの情報を確認しておいてください。
# NGN IPv6 Tunnel # Refer to # http://www.gcd.org/blog/2011/06/812/ # http://www.wandin.net/dotclear/index.php?post/2011/02/10/Native-IPv6-with-Internode- and-CentOS # http://www.ln-lab.net/lunar-night.lab/Memo/OCNIPv6/ocnipv6.html # http://lists.centos.org/pipermail/centos/2008-July/060532.html # USERCTL=yes BOOTPROTO=dialup NAME=DSLppp0 DEVICE=ppp0 TYPE=xDSL ONBOOT=no # # Ethernet Interface Name ETH=eth0 # # process id file PIDFILE=/var/run/pppoe-adsl.pid # # Don't set Firewall # FIREWALL=NONE # # print strings waiting for start up PING=. # # clamp advised MSS to 1412 byte CLAMPMSS=1412 # #DEFROUTE=yes # Don't use synchronous PPP SYNCHRONOUS=no #PROVIDER=DSLppp0 # keep connection DEMAND=no # # User USER=xxxxxxx@xxx.xxx.xxx.xxx # # PPPD Configuration # Time out of start up (sec) CONNECT_TIMEOUT=10 # # check delay time(sec) for start up CONNECT_POLL=2 # PPPD_EXTRA="ipv6 ," # # PPPoE Configuration # watch dog time(sec) for PPPoE PPPOE_TIMEOUT=80 # # retry count for LCP Echo LCP_FAILURE=3 # # send interval of LCP Echo LCP_INTERVAL=20 # # no request DNS server info. #USEPEERDNS=no PEERDNS=no # # IPv6 Configuration IPV6INIT=yes IPV6_AUTOCONF=no
# Secrets for authentication using CHAP # client server secret IP addresses "xxxxxx@xxx.xxx.xx.xx" * "(パスワードを入れる)"
実際にPPPoEを張るために、起動スクリプトを用意します。chkconfig により自動起動が可能なように記述します。
ファイルは /opt/ipv6_tools/ipv6_control.sh として作成します。作成後、実行可能なようにモードを a+x で変更してください。
#! /bin/sh # # # Startup/shutdown script for ipv6_control # # Linux chkconfig stuff: # # chkconfig: 2345 12 88 # description: Startup/shutdown script for ipv6_control # pidfile: # # Copyright 2012 Kazuhiro WATANABE # # These coded instructions, statements, and computer programs are the # property of kazuhiro WATANABE. # # Source function library. . /etc/init.d/functions IP_ADDR_CONV="/opt/ipv6_tools/ipv6_conv" PPPD_START_COMMAND="/usr/sbin/adsl-start" PPPD_STOP_COMMAND="/usr/sbin/adsl-stop" PPPD_CONFIG="/etc/sysconfig/network-scripts/ifcfg-ppp0" PPPD_PID_FILE="/var/run/ppp0.pid" DHCP6C_START_COMMAND="/usr/local/dhcpv6/dhcp6c" DHCP6C_STOP_COMMAND="killproc dhcp6c" DHCP6C_CONFIG="/etc/dhcp6c.conf" LAN_IF="eth0" PPP_IF="ppp0" RETVAL=0 start_ipv6() { test=`/sbin/ifconfig | /bin/grep ${PPP_IF}` if [ -n "$test" ] ; then echo "${PPP_IF} is already up" return 1 fi echo -n $"Starting PPP Connection: " # start ppp connection ${PPPD_START_COMMAND} ${PPPD_CONFIG} > /dev/null 2>&1 if [ -e $PPPD_PID_FILE ] ; then echo_success; /bin/logger -i -p user.info -t ipv6_control "Start PPP Connection: OK" else echo_failure; /bin/logger -i -p user.info -t ipv6_control "Start PPP Connection: NG" fi echo echo -n $"Starting IPv6 DHCP Client: " # start dhcp6 client ${DHCP6C_START_COMMAND} -c ${DHCP6C_CONFIG} ${PPP_IF} > /dev/null 2>&1 if [ $? == 0 ] ; then echo_success; /bin/logger -i -p user.info -t ipv6_control "Start IPv6 DHCP Client: OK" else echo_failure; /bin/logger -i -p user.info -t ipv6_control "Start IPv6 DHCP Client: NG" fi echo echo -n $"Setup routing: " # del default gateway /sbin/ip -6 route del default > /dev/null 2>&1 # add default gateway /sbin/ip -6 route add default dev ppp0 > /dev/null 2>&1 if [ $? == 0 ] ; then echo_success; /bin/logger -i -p user.info -t ipv6_control "Setup routing: OK" else echo_failure; /bin/logger -i -p user.info -t ipv6_control "Setup routing: NG" fi echo } stop_ipv6() { echo -n $"Delete routing: " # del default gateway /sbin/ip -6 route del default dev ppp0 > /dev/null 2>&1 if [ $? == 0 ] ; then echo_success; /bin/logger -i -p user.info -t ipv6_control "Delete routing: OK" else echo_failure; /bin/logger -i -p user.info -t ipv6_control "Delete routing: NG" fi echo echo -n $"Stopping IPv6 DHCP Client: " # stop dhcp6 client /usr/bin/killall ${DHCP6C_START_COMMAND} > /dev/null 2>&1 if [ $? == 0 ] ; then echo_success; /bin/logger -i -p user.info -t ipv6_control "Stop IPv6 DHCP Client: OK" else echo_failure; /bin/logger -i -p user.info -t ipv6_control "Stop IPv6 DHCP Client: NG" fi echo test=`/sbin/ifconfig | /bin/grep ${PPP_IF}` if [ -z "$test" ] ; then echo "${PPP_IF} is already down" return 1 fi echo -n $"Stopping IPv6 PPP Connection: " # stop ppp connection ${PPPD_STOP_COMMAND} ${PPPD_CONFIG} > /dev/null 2>&1 killproc pppd echo_success; /bin/logger -i -p user.info -t ipv6_control "Stop PPP Connection: OK" echo } show_address() { sleep 2 IP_ADDR=`/sbin/ifconfig | /bin/grep "/56" | /bin/sed -e "s/.*inet6 addr: \(.*\)\/56.*$/\1/"` if [ "${IP_ADDR} != "" ]; then echo -n " assigned Grobal address = " echo "${IP_ADDR}" echo -n " Prefix(64) address = " IP_ADDR_LOG=`${IP_ADDR_CONV} ${IP_ADDR}` PREFIX_64=`echo "${IP_ADDR}" | /bin/sed -e "s/\(.*:.*:.*:.*\):.*:.*:.*:.*$/\1/"` echo "${PREFIX_64}" /bin/logger -i -p user.info -t ipv6_control "IPv6 Address = ${IP_ADDR}(${PREFIX_64}/64)" else echo "No IPv6 Address is assigned" /bin/logger -i -p user.info -t ipv6_control "No IPv6 Address is assigned" fi } set_ipaddress() { /sbin/ip -6 route del default via fe80::xxxx:xxxx:xxxx:xxxx dev eth0 /sbin/ip -6 addr add ${PREFIX_64}::xxxx/64 dev ${LAN_IF} } del_ipaddress() { /sbin/ip -6 route del ${PREFIX_64}::/64 dev ${LAN_IF} /sbin/ip -6 addr del ${PREFIX_64}::xxxx/64 dev ${LAN_IF} /sbin/ip -6 route add default via fe80::xxxx:xxxx:xxxx:xxxx dev eth0 } start_radvd() { /bin/cat > /etc/radvd.conf <<EOF interface eth0 { AdvSendAdvert on; AdvOtherConfigFlag on; MinRtrAdvInterval 30; MaxRtrAdvInterval 100; prefix ${PREFIX_64}::/64 { AdvOnLink on; AdvAutonomous on; AdvRouterAddr off; }; }; EOF /sbin/service radvd start } stop_radvd() { /sbin/service radvd stop } start_dhcp6s() { /bin/cat > /etc/dhcp6s.conf <<EOF interface ${LAN_IF} { server-preference 255; renew-time 60; rebind-time 90; prefer-life-time 130; valid-life-time 200; allow rapid-commit; option dns_servers ${PREFIX_64}::xxxx; link AAA { range ${PREFIX_64}::ffff:1 to ${PREFIX_64}::ffff:100/64; }; }; EOF /sbin/service dhcp6s start } stop_dhcp6s() { /sbin/service dhcp6s stop } case $1 in start) /bin/logger -i -p user.info -t ipv6_control "Start IPv6 Control scripts..." start_ipv6 show_address set_ipaddress start_radvd start_dhcp6s /bin/logger -i -p user.info -t ipv6_control "IPv6 Control scripts done." ;; stop) /bin/logger -i -p user.info -t ipv6_control "Stop IPv6 Control scripts..." show_address stop_dhcp6s stop_radvd del_ipaddress stop_ipv6 /bin/logger -i -p user.info -t ipv6_control "IPv6 Control scripts done." ;; *) echo $"Usage: $0 {start|stop}" exit 3 esac exit $RETVAL
# ln -s /opt/ipv6_tools/ipv6_control.sh /etc/init.d/ipv6_control
# chkconfig --add ipv6_control # chkconfig --list ipv6_control ipv6_control 0:off 1:off 2:on 3:on 4:on 5:on 6:off #以上により自動サーバ起動時に自動的にPPPoEによりIPv6接続されます。
まず、コマンドベースで起動してみます。
# service ipv6_control start Starting PPP Connection: [ OK ] Starting IPv6 DHCP Client: [ OK ] Setup routing: [ OK ] assigned Grobal address = xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx Prefix(64) address = xxxx:xxxx:xxxx:xxxx RTNETLINK answers: No such process radvd を起動中: [ OK ] dhcp6s を起動中: [ OK ] #
ログはSyslogに User facilityで出力されます。Syslogの設定を変更していない場合は/var/log/messageに出力されます。なるべくuserファシリティは別ファイルに出力するように /etc/syslog.confを変更し、logrotateでログのローテーション設定を行ってください。
以上です。
お疲れ様でした。