PPPoE LAN型払い出し設定

よくあるフレッツ系回線収容するときにPPPoE IP8で契約してルータなりFWなりで受ける構成を組むときのメモ。IOSはそれなりにやっているから良いとして,SRXやFortigateで最近構築することがあるのでメモを残す。

LAN払い出し型の場合,ルータ単体では実装は難しい(というか無理)なようで別途RADIUSサーバを準備する必要がある。(TACACS+でもいけるかなと思ったが,RAIDUSの「Framed-IP-Address/Framed-IP-Netmask」に該当するものが見当たらなかったので素直にFreeradiusをDebianに入れることにした。)

FreeRADIUS準備

Debian10にfreeradiusを入れる。公式を見ると4.0はめちゃくちゃ面倒だからただ使いなら3.xつかえとあったのでそれに従う。

参考) https://networkradius.com/packages/#fr32-debian-buster

# apt install freeradius -y

結構時間がかかるけれど,これで完了。次にclient.confの編集。

# vi /etc/freeradius/3.0/client.conf
# 以下追加
client 192.168.1.3 {                         # PPPoEサーバのIPアドレス
        secret = secret-key                  # 認証用Key
}

続いてPPP認証用のユーザ設定。

# vi /etc/freeradius/3.0/user
# 以下追加
radius-user Cleartext-Password := "rad-secret"
        Service-Type = Framed-User,
        Framed-Protocol = PPP,
        Framed-IP-Address = 10.10.10.1,
        Framed-IP-Netmask = 255.255.255.248

RADIUS再起動。

# systemctl restart freeradius

PPPoEサーバ準備

次にIOS XE17系でPPPoEサーバの準備。(以下抜粋)

radius server FreeRadius
 address ipv4 <radiusのIP> auth-port 1812 acct-port 1813
 key secret-key
!
aaa new-model
!
!
aaa group server radius PPPoE
 server name FreeRadius
 ip radius source-interface GigabitEthernet0/4
!

aaa authentication ppp default group PPPoE
aaa authorization network default group PPPoE
aaa accounting network default start-stop group PPPoE
!

bba-group pppoe FLETS
 virtual-template 1
!
interface Loopback1
 ip address 172.17.1.1 255.255.255.0
!
interface GigabitEthernet1                   # RADIUSサーバと通信するIF
 ip address 192.168.1.3 255.255.255.0
 duplex auto
 speed auto
!
interface GigabitEthernet3                   # PPPoE接続用IF
 no ip address
 duplex auto
 speed auto
 pppoe enable group FLETS
!
interface Virtual-Template1
 mtu 1454
 ip unnumbered Loopback1
 ppp authentication chap
!

PPPoEクライアント設定

IOS 15.x系

interface GigabitEthernet0/0
 no ip address
 pppoe enable group global
 pppoe-client dial-pool-number 1
!
interface GigabitEthernet0/1
 ip address 10.10.10.1 255.255.255.248
!
interface Dialer0
 ip unnumbered GigabitEthernet0/1
 encapsulation ppp
 dialer pool 1
 dialer-group 1
 ppp authentication chap callin
 ppp chap hostname radius-user
 ppp chap password 0 rad-secret
!
ip route 0.0.0.0 0.0.0.0 Dialer0
!
dialer-list 1 protocol ip permit

JUNOS

このまんま。

set interfaces ge-0/0/0 unit 0 encapsulation ppp-over-ether
set interfaces ge-0/0/1 unit 0 family inet address 10.10.10.1/29
set interfaces fxp0 unit 0
set interfaces pp0 unit 1 ppp-options chap default-chap-secret "$9$eZBMxdbwgZGiN-kP5Q9CuO1Ervx7V2oG"
set interfaces pp0 unit 1 ppp-options chap local-name radius-user
set interfaces pp0 unit 1 ppp-options chap passive
set interfaces pp0 unit 1 pppoe-options underlying-interface ge-0/0/0.0
set interfaces pp0 unit 1 pppoe-options auto-reconnect 10
set interfaces pp0 unit 1 pppoe-options client
set interfaces pp0 unit 1 family inet unnumbered-address ge-0/0/1.0
set routing-options static route 0.0.0.0/0 next-hop pp0.1

Fortigate

WANのインタフェースにネットワークアドレス部分を入れないと駄目のようで,設定上気持ちが悪い。(が仕方が無いらしい)

system_interface:
    - wan:
        vdom: "FG-traffic"
        mode: pppoe
        allowaccess: ping
        type: physical
        lldp-reception: disable
        role: wan
        snmp-index: 1
        ipunnumbered: 10.10.10.0
        username: "radius-user"
        pppoe-unnumbered-negotiate: disable
        password: ENC xxxx
    - internal:
        vdom: "FG-traffic"
        ip: 10.10.10.1 255.255.255.248
        allowaccess: ping
        type: hard-switch
        device-identification: enable
        lldp-reception: disable
        lldp-transmission: disable
        role: lan
        snmp-index: 10

なお,PPPoEではないが,この構成でIPSecを行う際に送信元IPの指定がGUIでは「Local ID」しか設定することができず,CLIで「localid-type」を「address」に指定しないとPhase1の認証がこける。ここでハマって1日費やした。

EVE-NGでC1000vを起動してもネットワークに繋がらない問題

EVE-NGでCisco 1000vを起動したがネットワークに繋がらない問題に遭遇した。

見た目上特に正常に設定も入るのだが,インタフェースをいじると以下メッセージが出る。

[vmxnet3][WR][vmxnet3_get_command_status]: Received request for unknown command: cafe000f

キャプチャしてみるもパケットが一切観測されないので仮想マシン上でNICが正常に接続されていない風。

色々試した結果,解決方法はドライバを「vmnet3」から「virtio-net-pci」へ変更する。

これで無事に接続できた。EVE-NGオフィシャル動画を見るとvmnet3をつかえとなっているのだけど,ESXiのバージョンの違いなのかな。

2024/2/11 追記

このことを忘れていて暫くまた「繋がらないー」ともだえていた。テンプレートを修正しておく。

/opt/unetlab/html/templates/amd/ 配下にある csr1000vng.yml やc8000v.yml のNICを編集。

type: qemu
config_script: config_csr1000v.py
prep: prep_c8000v.sh
cstart: -cdrom config.iso
name: C8K
description: Cisco C8000V
cpulimit: 1
icon: CSRv1000.png
cpu: 2
ram: 4096
ethernet: 4
eth_format: Gi{1}
console: telnet
qemu_arch: x86_64
qemu_version: 2.4.0
qemu_nic: virtio-net-pci  # ここをvmxnet3から編集 
qemu_options: -machine type=pc,accel=kvm -cpu host -serial mon:stdio -nographic -no-user-config -nodefaults -rtc base=utc

これで次から気にしなくてよい。

IOSのパスワード文字列のハッシュ化について

enable secret などで利用する暗号化を指定したいとき,クリアテキストを入力することができない。

Router(config)#enable secret ?
  0      Specifies an UNENCRYPTED password will follow
  5      Specifies a MD5 HASHED secret will follow
  8      Specifies a PBKDF2 HASHED secret will follow
  9      Specifies a SCRYPT HASHED secret will follow
  <0-9>  Encryption types not explicitly specified
  LINE   The UNENCRYPTED (cleartext) 'enable' secret
  level  Set exec level password


事前にアルゴリズムを指定すれば良いだけなのだが,では,実際にハッシュ化された文字列を予め用意するにはどうしたらよいのだろうと考えた。

Router(config)#enable algorithm-type ?
  md5     Encode the password using the MD5 algorithm
  scrypt  Encode the password using the SCRYPT hashing algorithm
  sha256  Encode the password using the PBKDF2 hashing algorithm

Type5(MD5)

MD5の場合,opensslコマンドで対応できそうだ。オプションは-1がMD5。

$ openssl passwd --help
Usage: passwd [options]
Valid options are:
 -help               Display this summary
 -in infile          Read passwords from file
 -noverify           Never verify when reading password from terminal
 -quiet              No warnings
 -table              Format output as table
 -reverse            Switch table columns
 -salt val           Use provided salt
 -stdin              Read passwords from stdin
 -6                  SHA512-based password algorithm
 -5                  SHA256-based password algorithm
 -apr1               MD5-based password algorithm, Apache variant
 -1                  MD5-based password algorithm
 -aixmd5             AIX MD5-based password algorithm
 -crypt              Standard Unix password algorithm (default)
 -rand val           Load the file(s) into the random number generator
 -writerand outfile  Write random data to the specified file

いざお試し。opensslコマンドで生成。

$ openssl passwd -1 "password"
$1$.cR/0KTx$pPUO/YlCknfEryhGL8vZ7/

ルータへ投入。


Router(config)#enable secret 5 $1$.cR/0KTx$pPUO/YlCknfEryhGL8vZ7/
ERROR: The secret you entered is not a valid encrypted secret.
To enter an UNENCRYPTED secret, do not specify type 5 encryption.
When you properly enter an UNENCRYPTED secret, it will be encrypted.

エラーになる・・・。saltが必要だった。改めて生成。

$ openssl passwd -salt `openssl rand -base64 3`  -1 password
$1$tCLN$fofh2RhTlDmwzXeGUh7x4.

ルータへ投入。MD5はもはや非推奨だぞとアラートが出るが無事に行けた。

Router(config)#enable secret 5 $1$tCLN$fofh2RhTlDmwzXeGUh7x4.
 WARNING: Command has been added to the configuration using a type 5 password. However, type 5 passwords will soon be deprecated. Migrate to a supported password type
Router(config)#
*May 11 06:39:25.460: %AAAA-4-CLI_DEPRECATED: WARNING: Command has been added to the configuration using a type 5 password. However, type 5 passwords will soon be deprecated. Migrate to a supported password type

Type8(PBKDF2)

PBKDF2はSHA256で繰り返しハッシュ化するもの。

opensslではハッシュ化できなさそうなので,pythonでやってみる。Passlibというライブラリがあるのでこれを使う。

なお,Cisco Communityを見ると以下のように記載されている。

Type 8 passwords are what Type 4 was meant to be, an upgraded Type 5!  Type 8 is hashed using PBKDF2, SHA-256, 80-bit salt, 20,000 iterations. While this is good, it is still vulnerable to brute-forcing since AES is easy to implement in (GPU) graphics cards. I have not proven it but I believe it is possible that the popular tool HashCat is able to decrypt these. In the running config standard Type 8 start with $8$.

https://community.cisco.com/t5/networking-documents/understanding-the-differences-between-the-cisco-password-secret/ta-p/3163238

80バイトのSaltということは10文字,2万Iterationで試行。

$ pip install passlib
Collecting passlib
  Downloading passlib-1.7.4-py2.py3-none-any.whl (525 kB)
     |????????????????????????????????| 525 kB 21.2 MB/s
Installing collected packages: passlib
Successfully installed passlib-1.7.4
$ python
>>> from passlib.hash import pbkdf2_sha256
>>> pbkdf2_sha256.using(rounds=20000, salt_size=10).hash("password")
'$pbkdf2-sha256$20000$cm6t9T6n9L73ng$7sCcdbt9sNLWj5h7.Jd.7cdyLwYqoPlFMIWV1..hjFc'
>>> pbkdf2_sha256.verify("password", '$pbkdf2-sha256$20000$cm6t9T6n9L73ng$7sCcdbt9sNLWj5h7.Jd.7cdyLwYqoPlFMIWV1..hjFc')
True
>>>

ハッシュ化成功した模様。salt以降をCiscoに登録。

Router(config)#enable secret 8 $8$cm6t9T6n9L73ng$7sCcdbt9sNLWj5h7.Jd.7cdyLwYqoPlFMIWV1..hjFc
Router(config)#end
Router#disable
Router>en
Password:
Password:
Password:
% Bad secrets

なんでだ・・・。なんどやってもダメで,Cisco側で登録したハッシュを逆にverifyしてもダメだった(方式が違うっぽい)。そこで,こんなの(ciscoPWDhasher)があったのでこれを使ってみることにした。

$ git clone https://github.com/BrettVerney/ciscoPWDhasher.git
$ cd ciscoPWDhasher
$ pip install scrypt passlib backports.pbkdf2
$ python3 ./ciscopwdhasher.py

+------------------------------------------------------------------------+
|    ____ _                 ____                                     _   |
|   / ___(_)___  ___ ___   |  _ \ __ _ ___ _____      _____  _ __ __| |  |
|  | |   | / __|/ __/ _ \  | |_) / _` / __/ __\ \ /\ / / _ \| '__/ _` |  |
|  | |___| \__ \ (_| (_) | |  __/ (_| \__ \__ \\ V  V / (_) | | | (_| |  |
|   \____|_|___/\___\___/  |_|   \__,_|___/___/ \_/\_/ \___/|_|  \__,_|  |
|                                                                        |
|           _   _           _                                            |
|          | | | | __ _ ___| |__   ___ _ __      .--.                    |
|          | |_| |/ _` / __| '_ \ / _ \ '__|    /.-. '----------.        |
|          |  _  | (_| \__ \ | | |  __/ |       \'-' .--"--""-"-'        |
|          |_| |_|\__,_|___/_| |_|\___|_|        '--'                    |
|                                                                        |
|  by: Brett Verney (@WiFiWizardOFOz)                      version: 0.1  |
+------------------------------------------------------------------------+

Select a hashing algorithm:

[1]  Type 5 (MD5)
[2]  Type 7 (XOR Cipher)
[3]  Type 8 (PBKDF2-HMAC-SHA256)
[4]  Type 9 (Scrypt)
[5]  Exit

Your selection: 3

Enter a Plain Text Password to convert: password
Your Cisco type 7 password is:   #これ多分type 8の間違い $8$L7qc2XluRN/CzI$t34L8AK8SWb8LUFeCNVQanveK/JwKozfuAtHuIRH6vc

ルータへ設定。

Router(config)#enable secret 8 
 
Router(config)#end
Router#disa
Router#disable
Router>en
Password:
Router#

無事成功。どうやらbase64のエンコード周りでCisco形式に変換してあげないとダメみたい(良くわからない)。

Type9(Scrypt)

現在推奨の方式。

Select a hashing algorithm:

[1]  Type 5 (MD5)
[2]  Type 7 (XOR Cipher)
[3]  Type 8 (PBKDF2-HMAC-SHA256)
[4]  Type 9 (Scrypt)
[5]  Exit

Your selection: 4

Enter a Plain Text Password to convert: password
Your Cisco type 9 password is: $9$KvAkztzB8xe7Am$n3st6bOSv2hzH7qTG/9RHUInJ0DlbSmtTqOHOtn99UM

同じようにルータへ設定。

Router(config)#$qc2XluRN/CzI$t34L8AK8SWb8LUFeCNVQanveK/JwKozfuAtHuIRH6vc
Router(config)#end
Router#disa
Router#disable
Router>en
Password:
Router#

問題無し!

素直に enable algorithm-type を使えという話だけれど,たまにはこういうことを調べるのも良いね。

no ip domain-lookupからの卒業

Smart Licenseのおかげでスイッチにおいてもip domain-lookupの設定が必要になった。(環境によりけりが,インターネットダイレクト構成では少なくとも必要)

これを入れるとコマンド打ち間違えの時にdomain-lookupが発動してしまい,暫しご歓談をタイムに陥ってしまう。ミスタイプなどしないS級エンジニアや,「少しくらいの時間ならお茶を飲みながら待ちますよ」という賢者ならまだしも,ミスタイプをしょっちゅうするし少しの待ち時間ももったいない私にとっては致命的。

ということで方法はないかと調べてみると,あったのねこんな所に

“no ip domain-lookup”の代わりに”transport preferred none”

http://blog.livedoor.jp/tokyo_z/archives/51247251.html

間違えたコマンド入力を名前解決をしない方法

http://networkerslog.blog137.fc2.com/blog-entry-335.html

Transport preferred

https://community.cisco.com/t5/switching/transport-preferred/td-p/1612979

オフィシャルサイトでは以下のように説明がある。IOS XRだけど,基本同じだろう。

Cisco IOS XR ソフトウェア は、認識できないコマンドはすべてホスト名であるものと想定し、接続を試みます。 プロトコルが none に設定されている場合、システムは EXEC プロンプトで入力された認識できないコマンドを無視し、接続を試みません。

https://www.cisco.com/c/ja_jp/td/docs/rt/servprovideredgert/asr9000aggregationservsrt/cr/035/b_sysman_cr42asr9k/b_sysman_cr42asr9k_chapter_010010.html#wp2132003449

何かの名残でこのような設定になっているのかな。ちなみにIOS XRではデフォルト無効になっているそうだ。IOSやIOS XEでも同じくデフォルト無効にして欲しい。

以下設定コマンド。これでコマンド以外の文字列が入力されてもlookupが走らない(正確にはtelnetコマンドが実行されない)。

line con 0
 transport preferred none
line vty 0 4
 transport preferred none

NW機器のTACACS+設定

およそ世間では情報が沢山あるので我が家の設定値のみ記載。

設定方針は次の通り。

  • 1号機は.20,2号機は.21,TACACSサーバがダウンしたらLocal認証(タイムアウトは5秒)
  • ログインできたら即特権(コマンド権限はTACACSサーバ側で握る)
  • 1号機を最初に記述,2号機を次に記述
  • aaaの設定でdefaultとして定義するものをよく見かけるが,自宅環境では不採用とし,各aaaの定義に名前を付ける。(仮にdefaultで定義すると全てのインタフェースに適用されるし,設定順番ミスるとそのままコマンドがはじかれるなどリスクがあると思う。ただし,line vty でのauthentication設定などは不要になるなど設定行は減る。)

Cisco IOS

!!! AAA有効
aaa new-model

!!! TACACSサーバ登録。aaa tacacs-server は非推奨になった模様。
tacacs server tacacs-sv1
 address ipv4 192.168.30.20
 key <tacacsサーバで設定したKey>
 timeout 5
tacacs server tacacs-sv2
 address ipv4 192.168.30.21
 key <tacacsサーバで設定したKey>
 timeout 5

!!! TACACSサーバグループ作成。
aaa group server tacacs+ TAC_SRV
 server name tacacs-sv1
 server name tacacs-sv2

!!! TACplusという名前でTAC_SRVで登録したTACACSサーバに問い合わせる。落ちてたらローカル認証。
aaa authentication login TACplus_authe group TAC_SRV local-case


!!! 実行権限をTACACSサーバに問い合わせる。落ちてたらローカル認証。
aaa authorization exec TACplus_autho_exec group TAC_SRV local

!!! 実行レベル15のコマンド実行権限をTACACSサーバに問い合わせる。落ちてたらローカル認証。
aaa authorization commands 15 TACplus_autho_cmd group TAC_SRV local

!!! コマンド実行ログをTACACSサーバへ送信。
aaa accounting commands 15 TACplus_acco start-stop group TAC_SRV



line vty 0 4
 exec-timeout 0 0
 authorization commands 15 TACplus_autho_cmd
 authorization exec TACplus_autho_exec
 logging synchronous
 login authentication TACplus_authe
 transport input ssh

Cisco ASA

ASAの場合はIOSとは若干違うが,基本的な定義の流れは同じ。

aaa-server TACplus protocol tacacs+
 reactivation-mode timed
 max-failed-attempts 2
aaa-server TACplus (mgmtside) host 192.168.30.20
 key *****
aaa-server TACplus (mgmtside) host 192.168.30.21
 key *****

!!! SSH接続時にTACACS→LOCALという順で認証
aaa authentication ssh console TACplus LOCAL

!!! 特権
aaa authentication enable console TACplus LOCAL

aaa authorization command TACplus LOCAL
aaa accounting command privilege 15 TACplus

!!! 
aaa authorization exec authentication-server auto-enable
aaa authentication login-history

以上。

TACACS+サーバ構築

概要

宅内環境の認証をTACACS化しようと,まずはTACACS+サーバを2台立てる。構成は次の通り。各機器の管理IFと同じセグメントにTACACSサーバを2台建てる。

OpenStack上にDebianイメージでインスタンスを1つ。冗長化のためESXi上にUbuntuのVMをたてて2号機とする。(なぜOSが違うかというと,ESXi上にDebian10のイメージがなかっただけで特に他意はなし)

TACACS+はtac_plusを利用する。元はこれ(https://www.shrubbery.net/tac_plus/)だと思うのだが,公開が終わっているっぽい。facebookがGithubでforkしたものを公開していたので,Ubuntu側ではここからソースをもってきてコンパイルしてインストールした。’Debianはリポジトリからインストールできた。)

インストール

Debian 10でのインストール方法

aptで一発。

# apt install tacacs+

Debain11でのインストール方法

11にはまだパッケージがなかったためソースからコンパイル。

# apt install git build-essential flex bison libwrap0-dev
$ git clone https://github.com/facebook/tac_plus.git
$ cd tac_plus/tacacs-F4.0.4.28
$ ./configure
$ make
# make install

続いて必要なファイルの準備。

サービス起動ファイル /etc/init.d/tacacs_plus

#!/bin/sh
### BEGIN INIT INFO
# Provides:          tacacs+
# Required-Start:    $network $local_fs $syslog $remote_fs
# Required-Stop:     $network $local_fs $remote_fs
# Should-Start:      $named
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: TACACS+ authentication daemon
### END INIT INFO

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

DAEMON=/usr/local/sbin/tac_plus
NAME="tacacs+"
DESC="TACACS+ authentication daemon"
LOGDIR=/var/log/
STARTTIME=1

PIDFILE=/var/run/tac_plus.pid

test -x $DAEMON || exit 0

. /lib/lsb/init-functions

# Default options, these can be overriden by the information
# at /etc/default/$NAME
DAEMON_OPTS="-C /etc/tacacs+/tac_plus.conf"          # Additional options given to the server


LOGFILE=$LOGDIR/tac_plus.log  # Server logfile

# Include defaults if available
if [ -f /etc/default/$NAME ] ; then
        . /etc/default/$NAME
fi

# Check that the user exists (if we set a user)
# Does the user exist?
if [ -n "$DAEMONUSER" ] ; then
    if getent passwd | grep -q "^$DAEMONUSER:"; then
        # Obtain the uid and gid
        DAEMONUID=`getent passwd |grep "^$DAEMONUSER:" | awk -F : '{print $3}'`
        DAEMONGID=`getent passwd |grep "^$DAEMONUSER:" | awk -F : '{print $4}'`
    else
        log_failure_msg "The user $DAEMONUSER, required to run $NAME does not exist."
        exit 1
    fi
fi


set -e

running_pid() {
# Check if a given process pid's cmdline matches a given name
    pid=$1
    name=$2
    [ -z "$pid" ] && return 1
    [ ! -d /proc/$pid ] &&  return 1
    cmd=`cat /proc/$pid/cmdline | tr "\000" "\n"|head -n 1 |cut -d : -f 1`
    # Is this the expected server
    [ "$cmd" != "$name" ] &&  return 1
    return 0
}

running() {
# Check if the process is running looking at /proc
# (works for all users)

    # No pidfile, probably no daemon present
    [ ! -f "$PIDFILE" ] && return 1
    pid=`cat $PIDFILE`
    running_pid $pid $DAEMON || return 1
    return 0
}

start_server() {
# Start the process using the wrapper
    if check_config_quiet ; then
         start-stop-daemon --start --quiet --pidfile $PIDFILE \
                --exec $DAEMON -- $DAEMON_OPTS
         errcode=$?
         return $errcode
    else
         return $?
    fi

}

stop_server() {
    killproc -p $PIDFILE $DAEMON
    return $?
}

reload_server() {
    if check_config_quiet ; then
         [ ! -f "$PIDFILE" ] && return 1
         pid=`cat $PIDFILE` # This is the daemon's pid
         # Send a SIGHUP
         kill -1 $pid
         return $?
    else
         return $?
    fi
}

check_config() {
        $DAEMON -P $DAEMON_OPTS
        return $?
}

check_config_quiet() {
        $DAEMON -P $DAEMON_OPTS >/dev/null 2>&1
        return $?
}

force_stop() {
# Force the process to die killing it manually
        [ ! -e "$PIDFILE" ] && return
        if running ; then
                kill -15 $pid
        # Is it really dead?
                sleep "$DIETIME"s
                if running ; then
                        kill -9 $pid
                        sleep "$DIETIME"s
                        if running ; then
                                echo "Cannot kill $NAME (pid=$pid)!"
                                exit 1
                        fi
                fi
        fi
        rm -f $PIDFILE
}


case "$1" in
  start)
        log_daemon_msg "Starting $DESC " "$NAME"
        # Check if it's running first
        if running ;  then
            log_progress_msg "apparently already running"
            log_end_msg 0
            exit 0
        fi
        if start_server ; then
            # NOTE: Some servers might die some time after they start,
            # this code will detect this issue if STARTTIME is set
            # to a reasonable value
            [ -n "$STARTTIME" ] && sleep $STARTTIME # Wait some time
            if  running ;  then
                # It's ok, the server started and is running
                log_end_msg 0
            else
                # It is not running after we did start
                log_end_msg 1
            fi
        else
            # Either we could not start it
            log_end_msg 1
        fi
        ;;
  stop)
        log_daemon_msg "Stopping $DESC" "$NAME"
        if running ; then
            # Only stop the server if we see it running
                        errcode=0
            stop_server || errcode=$?
            log_end_msg $errcode
        else
            # If it's not running don't do anything
            log_progress_msg "apparently not running"
            log_end_msg 0
            exit 0
        fi
        ;;
  force-stop)
        # First try to stop gracefully the program
        $0 stop
        if running; then
            # If it's still running try to kill it more forcefully
            log_daemon_msg "Stopping (force) $DESC" "$NAME"
                        errcode=0
            force_stop || errcode=$?
            log_end_msg $errcode
        fi
        ;;
  restart|force-reload)
        log_daemon_msg "Restarting $DESC" "$NAME"
                errcode=0
        stop_server || errcode=$?
        # Wait some sensible amount, some server need this
        [ -n "$DIETIME" ] && sleep $DIETIME
        start_server || errcode=$?
        [ -n "$STARTTIME" ] && sleep $STARTTIME
        running || errcode=$?
        log_end_msg $errcode
        ;;
  status)

        log_daemon_msg "Checking status of $DESC" "$NAME"
        if running ;  then
            log_progress_msg "running"
            log_end_msg 0
        else
            log_progress_msg "apparently not running"
            log_end_msg 1
            exit 1
        fi
        ;;
  # Use this if the daemon cannot reload
  reload)
        log_daemon_msg "Reloading $DESC configuration files" "$NAME"
        if reload_server ; then
                if running ; then
                        log_end_msg 0
                else
                        log_progress_msg "$NAME not running"
                        log_end_msg 1
                fi
        else
                log_progress_msg "Reload failled"
                log_end_msg 1
        fi
        ;;
  check)
        check_config
        if [ X$? = "X0" ]
        then
                log_daemon_msg "Checking $DESC configuration files successful" "$NAME"
        else
                log_daemon_msg "Checking $DESC configuration files failed"
                exit 1
        fi
        ;;
  *)
        N=/etc/init.d/tacacs_plus
        echo "Usage: $N {start|stop|force-stop|restart|reload|force-reload|status|check}" >&2
        exit 1
        ;;
esac

exit 0

アカウンティングログファイル作成

# touch /var/log/tac_plus.acct

tacacs+設定ファイル編集(2台共通)

/etc/tacacs+/tac_plus

以下設定例。今回はとりあえず設定ファイル中にユーザを記述する設定方式をとったが,仕事ではやらないように注意。パスワードのハッシュ化は 「openssl passwd – 5」 (SHA256)で生成。

# アカウンティング用ログファイル指定
accounting file = /var/log/tac_plus.acct


# <サーバと通信するための鍵を記述>
key = tacacs_key

user = networkmanager {
        name = "Network Manager"
        member = admin
        login = des <ハッシュ化パスワード>
        enable = des <ハッシュ化enable>
}

user = networkoperator {
        name = "Read only user"
        member = operator
        login = des <ハッシュ化パスワード>
        enable = des <ハッシュ化enable>
}

# 管理者用グループ。Privilage15。
group = admin {
        default service = permit
        service = exec {
                priv-lvl = 15
        }

# オペレータ用グループ。showコマンドのみ利用可能
group = operator {
        default service = deny
        service = exec {
                priv-lvl = 15
        }
        cmd = show {
                permit .*
        }
        cmd = exit {
                permit .*
        }
}

TACACS+起動

# service tacacs_plus start

以上。

次はNW機器側の設定。

Catalyst3560CでGREトンネル

とある検証でL3SWでGREトンネルのみ張る設定を確認した。普通にいけるかなと思ったが,keepaliveでひっかかったのでメモ。

基本的には,Vlan IFにIPアドレスを設定し,tunnel source / destination でそれぞれ指定すれば完了。ただし,Keepaliveを設定するとDownとなる。デバッグをとっても応答が返ってこず(recieveが無い)Down判定されていた。

interface Tunnel1
 ip address 192.168.254.2 255.255.255.252
 keepalive 5 2
 tunnel source Vlan1
 tunnel destination 192.168.10.1

なんでだろうなと調べてみると,以下の一文を見つけた。

Support is available for gre ip tunnel mode. The tunnel source can be loopback and Layer 3 (physical or Etherchannel) interfaces only.

https://www.cisco.com/c/dam/en/us/td/docs/switches/lan/catalyst3850/software/release/16-1/workflows/gre-feature-guide.pdf

なるほど。型番もバージョンも違うけれどこれっぽい。試しにip routingを有効にしてLoopback IFを追加,対向のLoに対するスタティックルート追加したところ無事にkeepalive有りでトンネルが張れた。

枯れた技術だけれど,結構まだハマるところがあるという。精進が足りませんね。