【SSLVPN】OPNsense on Azure

クラウドへリモートアクセス環境を準備する場合,クラウドネイティブな方法もあるがVPN仮想アプライアンスをたててオンプレライクにSSLVPNで乗り込みたいシーンがよくある。(私の案件では)
クラウドにアカウントを作りたくない,プロトコルが対応していない等いくつか理由があるが,一番の理由は「クラウド構築担当している人がVPNとか全然分からんからNW部隊に丸投げしてくる。そんでもってユーザ管理や運用はそっちでやってね。」というもの。(

ぼやいても仕方ないので毎度VPN対応のFW仮想マシンをたてて構築するのだけれど,まぁ高いのなんの。そこで丁度よさそうなのがOPNsenseだったので構築手順を残しておく。

公式ドキュメントがあるので基本それに従って進めていく。
https://docs.opnsense.org/manual/how-tos/installazure.html

構成イメージ

バージョンは以下の通り。

サーバ側
OPNsense 24.1.1-amd64
FreeBSD 13.2-RELEASE-p9
OpenSSL 3.0.13

クライアント側
OpenVPN GUI v11.47.0.0

仮想マシン作成

ユーザ設定で認証を証明書にするとデプロイ失敗するのでパスワードを設定する。
パブリックIPとネットワークセキュリティグループを適切に設定してデプロイ完了したらHTTPSでログイン。

続いてSSLVPNの設定へ。

OPNsense設定

まずは認証関連の設定。今回は自己証明書で構成を組む。

CA作成

System: Trust: Authorities
※ 中身は省略

サーバ証明書作成

System: Trust: Certificates
※ 中身は省略

2FA用のGoogleAuth登録

System: Access: Servers
サーバ名を入れて,TypeでLocal+OTP。それ以外はそのまま。

SSLVPN Server作成

Serverを作成して~という流れはLegacyとあるのでインスタンスの作成。その前にTLS Keyを作成する。

認証用なのでAuthオンリーで。

入力したパラメータ一覧は以下の通り。それ以外は空欄ないしはデフォルトのまま。

GeneralSetting

  • Role: Server
  • Description: 適宜
  • Server(IPv4):172.16.1.0/24

Trust

  • Certificate: SSLVPN CRT(作成したサーバ証明書)
  • Certificate Authority: SSLVPN CA(作成したローカルCA)
  • Verify Client Certificate: none
  • Certificate Depth:One(Client+Server)
  • TLS static key: TSL-Key(作成したもの)
  • Auth:SHA256
  • Data Ciphers: AES-256-GCM

Authentication

  • Authentication: Google Auth(先ほど作成したもの)
  • Renegotiate time: 0 ※ OTP認証のため再接続になるとTokenが切れているため認証エラーとなってしまう。そのため,ここは「0」に設定する必要がある。OTPでなければ不要。

Routing

  • Local Network: 10.0.0.0/16 (VNetにアクセスできれば良いのでVNetに割り当てたセグメント指定)

SNAT設定

VPNのトラフィックをインタフェースでSNATする。
Modeをマニュアルへ変更。

Interface,Source addressをそれぞれ設定。

結果。

リモートアクセスユーザ作成

ユーザ名,パスワードを入力し,OTP用の設定を入力する。

ここでSaveをするとユーザ証明書作成ページに跳ぶ。自己証明書作成を選択し、その他項目も適宜入力して作成する。

その後,GoogleAuthenticatorへ登録するためのQRコードが生成されるのでスマホアプリで登録する。

OpenVPNClient設定エクスポート

TypeはFileonly。Windowsの証明書ストアのオプションは外す。

一番下にあるユーザ用の構成ファイルをダウンロードして完了。

FW設定

今回,Azure上で構築しているので通信制御はNetworkSecurityGroupで対応することとして,OPNsenseのルールは全許可とした。よってここは省略。(LANとOpenVPNのIFにIN全許可ルールを1行入れたのみ)

接続試験(Windows11)

サーバ側でも設定した再認証させない設定をダウンロードしたファイルにも追記する必要がある。

dev tun
persist-tun
persist-key
auth SHA256
client
verb 5  # デバッグ用
ping-restart 0  # これ0に指定する必要がある
resolv-retry infinite

保存した設定ファイルをOpenVPNクライアントにインポートし,接続すると認証画面が出るので「 Token + Password 」の並びで入力する。これが分からなくてサーバ設定見直したりキャプチャ眺めたり,VM作り直したりとかなり迷走した orz。

無事に成功するとIPアドレスが割り当てられAzure内に通信できるようになる。

疎通確認

無事Pingも通った。

ping 172.16.1.1  # Tunnel対向

172.16.1.1 に ping を送信しています 32 バイトのデータ:
172.16.1.1 からの応答: バイト数 =32 時間 =187ms TTL=64
172.16.1.1 からの応答: バイト数 =32 時間 =186ms TTL=64

172.16.1.1 の ping 統計:
    パケット数: 送信 = 2、受信 = 2、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
    最小 = 186ms、最大 = 187ms、平均 = 186ms
Ctrl+C
^C

>ping 10.0.0.5 -t # VPNサーバAzure内部IP

10.0.0.5 に ping を送信しています 32 バイトのデータ:
10.0.0.5 からの応答: バイト数 =32 時間 =187ms TTL=64
10.0.0.5 からの応答: バイト数 =32 時間 =187ms TTL=64

10.0.0.5 の ping 統計:
    パケット数: 送信 = 2、受信 = 2、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
    最小 = 187ms、最大 = 187ms、平均 = 187ms
Ctrl+C
^C

>ping 10.0.0.4 -t # Azure内同一Subnet別インスタンス

10.0.0.4 に ping を送信しています 32 バイトのデータ:
10.0.0.4 からの応答: バイト数 =32 時間 =189ms TTL=63
10.0.0.4 からの応答: バイト数 =32 時間 =189ms TTL=63

10.0.0.4 の ping 統計:
    パケット数: 送信 = 2、受信 = 2、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
    最小 = 189ms、最大 = 189ms、平均 = 189ms
Ctrl+C
^C

以上で完了。おつかれさまでした。

VLAN Trunkポートのキャプチャ

Trunkポートを流れるパケットのVLANタグをWiresharkでキャプチャしたい。と思ったときに思いのほか手順が多かったのでメモとして残す。

ざっくり手順

上記構成でパケットキャプチャの手順は次の通り。

  1. SW1にてキャプチャの設定
  2. キャプチャを行うPCで802.1qのタグを落とさないよう,キャプチャを取得するNICのドライバ設定
  3. Wiresharkで802.1qのタグをキャプチャ画面の列に表示するよう設定

通常のアクセスポートでキャプチャを行うだけであれば意識することなくできると思うが,VLAN Trunkポートにおいては各手順でいつもと違う設定が必要になる。

SW1でmonitor session 設定

通常のキャプチャであれば

monitor session 1 source interface Gi0/1
monitor session 1 destination interface Gi0/2

とシンプルに設定をすればよいが,デフォルトではタグ情報を外して宛先ポートへパケットが転送されるため「encapsulation」オプションで「replicate / dot1q」を指定する必要がある。カプセル化でISLを設定するケースはまず無いと思うので,このオプションはdot1qでTrunk設定しているならばどちらでも良いと思う。オプションの違いは,送信元IFと同じカプセル化・設定を指定する場合は「replicate」,dot1qの設定とするならば「dot1q」という感じ。(※ IOSの場合)

なお,受信パケットでにおいて特定のVLANを限定して取得したい場合は「ingress dot1q vlan」オプションでVLAN IDを指定する。

(任意)宛先インターフェイスで IEEE 802.1Q カプセル化方式の使用を指定するには、 encapsulation dot1q を入力します。
(任意)送信元インターフェイスのカプセル化方式が宛先インターフェイスで複製されるように指定するには、 encapsulation replicate を入力します。これを選択しない場合、デフォルトでは、パケットがネイティブ形式(タグなし)で送信されます。
宛先ポートでの着信トラフィックの転送をイネーブルにして、カプセル化タイプを指定するには、 ingress をキーワードと一緒に入力します。
– dot1q vlan vlan-id: デフォルトの VLAN として指定した VLAN で、IEEE 802.1Q でカプセル化された着信パケットを受信します。
– untagged vlan vlan-id または vlan vlan-id: デフォルトの VLAN として指定した VLAN で、タグなしでカプセル化された着信パケットを受信します。

cisco.com/c/ja_jp/td/docs/sw/lanswt-access/cat2960swt/cg/005/swcfg/swspan.html

よって次のような設定を入れる。

monitor session 1 source interface Gi0/1
monitor session 1 destination interface Gi0/2 encapsulation replicate  # dot1q でもOK

NICの設定

およそのNICはデフォルトでVLANタグを落とす設定になっているため,NICの詳細設定で「Packet Priority&VLAN」を「Disable」にする。※デフォルトでは「Enable」になっているはず

この設定ができない(VLANタグをそのまま受信できない)NICもあるようで,NICの対応状況は予めチェックが必要。今回利用したNICはStarTechのUSBタイプ。

Wiresharkの設定

Wiresharkのキャプチャ画面の項目(列)にはVLAN情報がデフォルトでは表示されないため,VLAN IDを表示させるため外観設定を変更する。パケットを選択すればVLANフィールドがあるので別に要らないという人はここはやらなくてもOK。ただぱっと見どのVLANか分かるので可視性はよい。

Wiresharkを立ち上げ,「編集」→「設定」で設定画面表示。

「+」ボタンを押してフィールドを追加し,フィールドに「vlan.id」を入力する。題名はお好きなように。ここでは「VLAN」とした。

これで準備完了。

キャプチャする

VLANが表示されて幸せになれる。

ちなみに,QinQを表示させたい場合は,Wiresharkで追加するフィールドに「ieee8021ad.id1」を入力する。

  1. Display Filter Reference: IEEE 802.1ad (https://www.wireshark.org/docs/dfref/i/ieee8021ad.html ↩︎

phpIPAMインストールメモ

IPAM: IP Address Management

その名の通りアドレス管理ツールで,以前NetBoxを遣ってみたがアドレス管理だけに焦点をあてると too muchな感じだったので別のものを探していた。

そこでphpipamを見かけたので試した。

結論からいうと,こちらのほうが自分には合っていた。

OpenStackにMiracleLinux9をたて,そこへインストールする。

事前準備

必要要件を確認。正直PHPなど触ったことも無いので良くわからない。

https://phpipam.net/documents/installation/

  • Webserver (今回はnginx にした)
  • Mysql server (Mariadb)
  • PHP
  • PHP module
  • php PEAR

まず上記含めてインストールに必要なものを準備。

# dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
# dnf install nginx
# dnf install mariadb-server 
# dnf install php
# dnf install php-{pdo,pdo_mysql,session,sockets,openssl,gmp,ldap,xml,json,gettext,filter,pcntl,pear,gd}
# dnf install git
# systemctl enable nginx php-fpm mariadb
# systemctl start nginx php-fpm mariadb

phpipamダウンロード。

# git clone  --recursive https://github.com/phpipam/phpipam.git /var/www/phpipam
# cd /var/www/phpipam
# git checkout -b 1.5 origin/1.5
# chown -R nginx:nginx /var/www/

Mariadb初期設定。

# mysql_secure_installation
NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!

In order to log into MariaDB to secure it, we'll need the current
password for the root user. If you've just installed MariaDB, and
haven't set the root password yet, you should just press enter here.

Enter current password for root (enter for none):
OK, successfully used password, moving on...

Setting the root password or using the unix_socket ensures that nobody
can log into the MariaDB root user without the proper authorisation.

You already have your root account protected, so you can safely answer 'n'.

Switch to unix_socket authentication [Y/n] y
Enabled successfully!
Reloading privilege tables..
 ... Success!


You already have your root account protected, so you can safely answer 'n'.

Change the root password? [Y/n] y
New password:
Re-enter new password:
Password updated successfully!
Reloading privilege tables..
 ... Success!


By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] y
 ... Success!

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] y
 ... Success!

By default, MariaDB comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] y
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] y
 ... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MariaDB
installation should now be secure.

Thanks for using MariaDB!

ipam用DBユーザ作成。

# mysql -u root -p
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 13
Server version: 10.5.16-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> create database phpipam;
Query OK, 1 row affected (0.000 sec)

MariaDB [(none)]> GRANT ALL on phpipam.* to phpipam@localhost identified by 'PASSWORD';
Query OK, 0 rows affected (0.050 sec)

MariaDB [(none)]> exit
Bye

スキーマ取り込み。

# mysql -u root -p phpipam < ./db/SCHEMA.sql

設定ファイル編集

設定ファイルをコピー。

# cp /var/www/phpipam/config.dist.php /var/www/phpipam/config.php

DB認証関連パラメータを編集。

# vi /var/www/phpipam/config.php
/**
 * database connection details
 ******************************/
$db['host'] = '127.0.0.1';
$db['user'] = 'phpipam';
$db['pass'] = 'phpipamadmin';
$db['name'] = 'phpipam';
$db['port'] = 3306;


/***
 このままいくと以下メッセージが出るのでPHPのバージョンをサポート外でも起動させるオプションを入れる 
Detected PHP version: 8.0.27 >= 8.0
***/

$allow_untested_php_versions=true;

php.iniのタイムゾーンを設定。

# vim /etc/php.ini
[Date]
; Defines the default timezone used by the date functions
; http://php.net/date.timezone
date.timezone = Asia/Tokyo

nginx周りの設定ファイル編集。

/etc/nginx/nginx.conf のサーバセクションをコメントアウト。

# vi /etc/nginx/nginx.conf
#    server {
#        listen       80;
#        listen       [::]:80;
#        server_name  _;
#        root         /usr/share/nginx/html;
#
#        # Load configuration files for the default server block.
#        include /etc/nginx/default.d/*.conf;
#
#        error_page 404 /404.html;
#        location = /404.html {
#        }
#
#        error_page 500 502 503 504 /50x.html;
#        location = /50x.html {
#        }
#    }

phpipam用に以下設定ファイル作成。公式参照しつつググった結果をもとに適宜修正。

# vi /etc/nginx/conf.d/phpipam.conf
server {
    # root directory
    root   /var/www/phpipam/;
   
    # phpipam
    location / {
        try_files $uri $uri/ index.php;
        index index.php;
    }
    # phpipam - api
    location /api/ {
        try_files $uri $uri/ /api/index.php;
    }

    # php-fpm
    location ~ \.php$ {
        fastcgi_pass   unix:/var/run/php-fpm/www.sock;
        fastcgi_index  index.php;
        try_files      $uri $uri/ index.php = 404;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
 }

php-fpm.conf のソケットのパスを適切に修正。

# vi /etc/nginx/conf.d/php-fpm.conf
# PHP-FPM FastCGI server
# network or unix domain socket configuration

upstream php-fpm {
        server unix:/var/run/php-fpm/www.sock;
}

アクセス許可

SELinuxとfirewalldでHTTP(80)を許可する。

# firewall-cmd --add-service=http --zone=public --permanent
# firewall-cmd --reload
# sudo setsebool -P httpd_can_network_connect 1

初期設定

これでhttp://ipaddress/ にアクセスすると以下画面が出て初期セットアップに入る。

ポチポチやっていくと初期パスでログイン→パス変更→ダッシュボードへと遷移する。

これでセットアップは完了。後はIPアドレス管理のための準備となるが割愛。

OpenStack コンテナサービス(zun)追加

All-in-oneのPackstack環境にコンテナサービスのzunを追加する手順をインストールメモがてら残した。

手順はここ(https://docs.openstack.org/zun/latest/install/controller-install.html)を参照。

コントローラノード向け設定

データベースにユーザ追加

# mysql
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 3728741
Server version: 10.3.35-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> GRANT ALL PRIVILEGES ON zun.* TO 'zun' \
  IDENTIFIED BY 'ZUN_DBPASS';
Query OK, 0 rows affected (0.000 sec)
MariaDB [(none)]> GRANT ALL PRIVILEGES ON zun.* TO 'zun'@'%' \
  IDENTIFIED BY 'ZUN_DBPASS';
Query OK, 0 rows affected (0.000 sec)

MariaDB [(none)]> quit
Bye
#

zun service作成。

$ . admin-openrc
$ openstack user create --domain default --password-prompt zun
User Password:
Repeat User Password:
+---------------------+----------------------------------+
| Field               | Value                            |
+---------------------+----------------------------------+
| domain_id           | default                          |
| enabled             | True                             |
| id                  | f4f40696f6914b5b9e9054b7e9cfb55d |
| name                | zun                              |
| options             | {}                               |
| password_expires_at | None                             |
+---------------------+----------------------------------+

$ openstack role add --project services --user zun admin

$ openstack service create --name zun --description "Container Service" container
+-------------+----------------------------------+
| Field       | Value                            |
+-------------+----------------------------------+
| description | Container Service                |
| enabled     | True                             |
| id          | 74d60a5188ee4d36b1ba036c23c45f2e |
| name        | zun                              |
| type        | container                        |
+-------------+----------------------------------+
$  openstack endpoint create --region RegionOne container public http://192.168.1.10:9517/v1
+--------------+----------------------------------+
| Field        | Value                            |
+--------------+----------------------------------+
| enabled      | True                             |
| id           | ae352beaa62c45899da2ec57d376e2ab |
| interface    | public                           |
| region       | RegionOne                        |
| region_id    | RegionOne                        |
| service_id   | 74d60a5188ee4d36b1ba036c23c45f2e |
| service_name | zun                              |
| service_type | container                        |
| url          | http://192.168.1.10:9517/v1      |
+--------------+----------------------------------+
$ openstack endpoint create --region RegionOne container internal http://192.168.1.10:9517/v1
+--------------+----------------------------------+
| Field        | Value                            |
+--------------+----------------------------------+
| enabled      | True                             |
| id           | d1e241ca8f664f05b1976c5a5628a284 |
| interface    | internal                         |
| region       | RegionOne                        |
| region_id    | RegionOne                        |
| service_id   | 74d60a5188ee4d36b1ba036c23c45f2e |
| service_name | zun                              |
| service_type | container                        |
| url          | http://192.168.1.10:9517/v1      |
+--------------+----------------------------------+
$ openstack endpoint create --region RegionOne container admin http://192.168.1.10:9517/v1
+--------------+----------------------------------+
| Field        | Value                            |
+--------------+----------------------------------+
| enabled      | True                             |
| id           | 911e3f76ba09463bad2833573bfb17ef |
| interface    | admin                            |
| region       | RegionOne                        |
| region_id    | RegionOne                        |
| service_id   | 74d60a5188ee4d36b1ba036c23c45f2e |
| service_name | zun                              |
| service_type | container                        |
| url          | http://192.168.1.10:9517/v1      |
+--------------+----------------------------------+

OSユーザ追加。

# groupadd --system zun
# useradd --home-dir "/var/lib/zun" \
      --create-home \
      --system \
      --shell /bin/false \
      -g zun \
      zun
# mkdir -p /etc/zun
# chown zun:zun /etc/zun
# dnf install python3-pip git python3-devel libffi-devel gcc openssl-devel
Updating Subscription Management repositories.
Last metadata expiration check: 2:15:22 ago on Fri 06 Jan 2023 07:01:20 PM JST.
Package python3-pip-9.0.3-22.el8.noarch is already installed.
Package git-2.31.1-2.el8.x86_64 is already installed.
Package python36-devel-3.6.8-38.module+el8.5.0+12207+5c5719bc.x86_64 is already installed.
Package gcc-8.5.0-15.el8.x86_64 is already installed.
Dependencies resolved.
=============================================================================================================================================================================
 Package                                    Architecture                  Version                                 Repository                                            Size
=============================================================================================================================================================================
Installing:
 libffi-devel                               x86_64                        3.1-23.el8                              rhel-8-for-x86_64-baseos-rpms                         29 k
 openssl-devel                              x86_64                        1:1.1.1k-7.el8_6                        rhel-8-for-x86_64-baseos-rpms                        2.3 M
Installing dependencies:
 keyutils-libs-devel                        x86_64                        1.5.10-9.el8                            rhel-8-for-x86_64-baseos-rpms                         48 k
 krb5-devel                                 x86_64                        1.18.2-22.el8_7                         rhel-8-for-x86_64-baseos-rpms                        561 k
 libcom_err-devel                           x86_64                        1.45.6-5.el8                            rhel-8-for-x86_64-baseos-rpms                         39 k
 libkadm5                                   x86_64                        1.18.2-22.el8_7                         rhel-8-for-x86_64-baseos-rpms                        187 k
 libselinux-devel                           x86_64                        2.9-6.el8                               rhel-8-for-x86_64-baseos-rpms                        200 k
 libsepol-devel                             x86_64                        2.9-3.el8                               rhel-8-for-x86_64-baseos-rpms                         87 k
 libverto-devel                             x86_64                        0.3.2-2.el8                             rhel-8-for-x86_64-baseos-rpms                         18 k
 pcre2-devel                                x86_64                        10.32-3.el8_6                           rhel-8-for-x86_64-baseos-rpms                        605 k
 pcre2-utf16                                x86_64                        10.32-3.el8_6                           rhel-8-for-x86_64-baseos-rpms                        229 k
 pcre2-utf32                                x86_64                        10.32-3.el8_6                           rhel-8-for-x86_64-baseos-rpms                        220 k

Transaction Summary
=============================================================================================================================================================================
Install  12 Packages

Total download size: 4.5 M
Installed size: 8.0 M
Is this ok [y/N]: y
~中略~
Installed:
  keyutils-libs-devel-1.5.10-9.el8.x86_64       krb5-devel-1.18.2-22.el8_7.x86_64       libcom_err-devel-1.45.6-5.el8.x86_64       libffi-devel-3.1-23.el8.x86_64
  libkadm5-1.18.2-22.el8_7.x86_64               libselinux-devel-2.9-6.el8.x86_64       libsepol-devel-2.9-3.el8.x86_64            libverto-devel-0.3.2-2.el8.x86_64
  openssl-devel-1:1.1.1k-7.el8_6.x86_64         pcre2-devel-10.32-3.el8_6.x86_64        pcre2-utf16-10.32-3.el8_6.x86_64           pcre2-utf32-10.32-3.el8_6.x86_64

Complete!

# cd /var/lib/zun
# git clone https://opendev.org/openstack/zun.git
Cloning into 'zun'...
remote: Enumerating objects: 12578, done.
remote: Counting objects: 100% (12578/12578), done.
remote: Compressing objects: 100% (2355/2355), done.
remote: Total 25247 (delta 12095), reused 10223 (delta 10223), pack-reused 12669
Receiving objects: 100% (25247/25247), 3.88 MiB | 4.09 MiB/s, done.
Resolving deltas: 100% (19377/19377), done.
# chown -R zun:zun zun
# git config --global --add safe.directory /var/lib/zun/zun
# cd zun
# pwd
/var/lib/zun/zun
# pip3 install -r requirements.txt
~中略~
Successfully installed docker-5.0.3 grpcio-1.48.2 kuryr-lib-2.6.0 protobuf-3.19.6 websocket-client-1.3.1
# python3 setup.py install

# su -s /bin/sh -c "oslo-config-generator --config-file etc/zun/zun-config-generator.conf" zun
# su -s /bin/sh -c "cp etc/zun/zun.conf.sample /etc/zun/zun.conf" zun
# su -s /bin/sh -c "cp etc/zun/api-paste.ini /etc/zun" zun

zun.conf 編集

# vim /etc/zun/zun.conf
[DEFAULT]
...
transport_url = rabbit://guest:PASS@192.168.1.10:5672/

[api]
...

port = 9517
[database]
...
connection=mysql+pymysql://zun:ZUN-PASS@192.168.1.10/zun
[keystone_auth]
...
auth_url=http://192.168.1.10:5000
project_domain_name = Default
username = zun
password = PASS

[keystone_authtoken]
...

www_authenticate_uri = http://192.168.1.10:5000/

auth_version = v3

username = zun
password = PASS
auth_protocol = http

[oslo_concurrency]
lock_path = /var/lib/zun/tmp

[websocket_proxy]
base_url = ws://$wsproxy_host:$wsproxy_port/
wsproxy_host = 192.168.1.10

wsproxy_port = 6784

DBアップデート

# su -s /bin/sh  -c "/usr/local/bin/zun-db-manage upgrade"  zun

起動スクリプト作成

# /etc/systemd/system/zun-api.service
[Unit]
Description = OpenStack Container Service API

[Service]
ExecStart = /usr/local/bin/zun-api
User = zun

[Install]
WantedBy = multi-user.target

# /etc/systemd/system/zun-wsproxy.service
[Unit]
Description = OpenStack Container Service Websocket Proxy

[Service]
ExecStart = /usr/local/bin/zun-wsproxy
User = zun

[Install]
WantedBy = multi-user.target

サービス起動

# systemctl enable zun-api zun-wsproxy
# systemctl start zun-api zun-wsproxy

コンピュートノード向け設定

All-in-One構成なのでコントローラと重複するところはスキップして差分だけ実施。

DockerとKuryr,Etcdを先にインストールする。

# Docker install
dnf config-manager ―-add-repo https://download.docker.com/linux/rhel/docker-ce.repo

RHEL8からはPodmanになったとのことでリポジトリのBaseURLをCentOSに変更しないとdockerをインストールできないらしい。

# vim /etc/yum.repos.d/docker-ce.repo

[docker-ce-stable]
name=Docker CE Stable - $basearch
#baseurl=https://download.docker.com/linux/fedora/$releasever/$basearch/stable #コメントアウト
baseurl=https://download.docker.com/linux/centos/$releasever/$basearch/stable # 追加

Dockerインストール

# dnf install docker-ce docker-ce-cli containerd.io docker-compose-plugin

Kuryr-libnetworkインストール

<https://docs.openstack.org/kuryr-libnetwork/latest/install/controller-install.html>

$ openstack user create --domain default --password-prompt kuryr
$ openstack role add --project services --user kuryr admin

<https://docs.openstack.org/kuryr-libnetwork/latest/install/compute-install-ubuntu.html#prerequisites>

# groupadd --system kuryr
# useradd --home-dir "/var/lib/kuryr" --create-home --system --shell /bin/false -g kuryr kuryr
#  mkdir -p /etc/kuryr
# chown kuryr:kuryr /etc/kuryr
# cd /var/lib/kuryr/
# git clone -b master https://opendev.org/openstack/kuryr-libnetwork.git
# chown -R kuryr:kuryr kuryr-libnetwork
# cd kuryr-libnetwork/
# python3 setup.py install

# su -s /bin/sh -c "./tools/generate_config_file_samples.sh" kuryr
# su -s /bin/sh -c "cp etc/kuryr.conf.sample /etc/kuryr/kuryr.conf" kuryr

設定ファイル編集。

# /etc/kuryr/kuryr.conf

[DEFAULT]
...
bindir = /usr/local/libexec/kuryr

[neutron]
...
auth_url = http://192.168.1.10:5000/
www_authenticate_uri = http://192.168.1.10:5000/
username = kuryr
user_domain_name = Default
password = PASSWORD
project_name = services
project_domain_name = Default
auth_type = password

Etcdインストール

# dnf list installed etcd

# vim /etc/etcd/etcd.conf

ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="http://192.168.1.10:2380"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
ETCD_NAME="controller"
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.1.10:2379"
ETCD_INITIAL_CLUSTER="default=http://192.168.1.10:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"

ZUN設定

# mkdir -p /etc/cni/net.d
# chown zun:zun /etc/cni/net.d/

# dnf install numactl

# su -s /bin/sh -c "cp etc/zun/rootwrap.conf /etc/zun/rootwrap.conf" zun
# su -s /bin/sh -c "mkdir -p /etc/zun/rootwrap.d" zun
# su -s /bin/sh -c "cp etc/zun/rootwrap.d/*  /etc/zun/rootwrap.d/" zun
# su -s /bin/sh -c "cp etc/cni/net.d/* /etc/cni/net.d/" zun

# echo "zun ALL=(root) NOPASSWD: /usr/local/bin/zun-rootwrap /etc/zun/rootwrap.conf *" | sudo tee /etc/sudoers.d/zun-rootwrap zun ALL=(root) NOPASSWD: /usr/local/bin/zun-rootwrap     /etc/zun/rootwrap.conf *
# /etc/zun/zun.conf

[DEFAULT]
...
state_path = /var/lib/zun

[compute]
...
host_shared_with_nova = true

Docker と Kuryr 設定

# mkdir -p /etc/systemd/system/docker.service.d

dockerサービス起動設定

# /etc/systemd/system/docker.service.d/docker.conf
[Service]

ExecStart=
ExecStart=/usr/bin/dockerd --group zun -H tcp://192.168.1.10:2375 -H unix:///var/run/docker.sock --cluster-store etcd://192.168.1.10:2379

containerd設定ファイル生成

# containerd config default > /etc/containerd/config.toml

containerd設定ファイル編集

# /etc/containerd/config.toml

[grpc]
  ...
  gid = ZUN_GROUP_ID

再起動

# systemctl restart containerd

CNIインストール&設定

# mkdir -p /opt/cni/bin
# curl -L https://github.com/containernetworking/plugins/releases/download/v0.7.1/cni-plugins-amd64-v0.7.1.tgz | tar -C /opt/cni/bin -xzvf - ./loopback

# install -o zun -m 0555 -D /usr/local/bin/zun-cni /opt/cni/bin/zun-cni

サービス設定

# /etc/systemd/system/zun-compute.service
[Unit]
Description = OpenStack Container Service Compute Agent

[Service]
ExecStart = /usr/local/bin/zun-compute
User = zun

[Install]
WantedBy = multi-user.target
# /etc/systemd/system/zun-cni-daemon.service
[Unit]
Description = OpenStack Container Service CNI daemon

[Service]
ExecStart = /usr/local/bin/zun-cni-daemon
User = zun

[Install]
WantedBy = multi-user.target

サービス起動

# systemctl enable zun-compute zun-cni-daemon
# systemctl start zun-compute zun-cni-daemon

ここを参考。(https://docs.openstack.org/zun-ui/latest/)

Horizen周り設定

$ git clone https://github.com/openstack/zun-ui
$ cd zun-ui

$ sudo pip3 install .

$ sudo cp ./zun_ui/enabled/* /usr/share/openstack-dashboard/openstack_dashboard/local/enabled
$ sudo python3 /usr/share/openstack-dashboard/manage.py collectstatic

$ sudo systemctrl restart httpd

これで完了。

FSのワイヤレス設定

先日FSの無線LANコントローラとAPが届いたのでセットアップを行った。かなりCiscoと勝手が違うため結構困惑したので最低限のメモを残す。(設定の手がかりが公式のドキュメント(英語PDF)のみで,環境構築までの一連の流れが正直わかりにくかった。)

※ 2023/3/11 コントローラ設定でdhcp-detectを無効化しないとコントローラーIPが再起動時に消えてしまう問題があったため追記。

調達したのは以下の通り。

  • 無線LANコントローラ AC-1004
  • 無線LANアクセスポイント AP-N505

構成は端折ってこんな感じ。VLAN30(192.168.30.0/24)を管理セグメントとしているので,コントローラ(以下AC)もAPもVLAN30のIPアドレスを割り当てる。AC~AP間のメッセージはAPの管理IPはデフォルトVLANを使うため,APが接続するポートはVLAN30をデフォルトVLANに設定する。

AC(コントローラ)設定

コンソールポートに接続し(初期admin/admin),ホスト名,管理IPアドレス,CAPWAP用IPアドレス,AP接続用ポート設定を行う。CiscoライクなCLIなのでコマンドで困ることはほぼなかった。

conf t
!
hostname home-wlc
!
! ※ ↓これをいれないとctrl-ipが再起動時に有効にならない
dhcp-detect disable
!
!
ac-controller
 capwap ctrl-ip 192.168.30.15
 country JP
!
! ※ 2023/3/11 追記この定義を入れないと設定上 capwap ctrl-ip の設定が入っていても消えてしまう
dhcp-detect disable  
!
username XXXX privilege 15 password XXXX
!
clock timezone UTC +9 0
!
interface GigabitEthernet 0/0
 description UPLINK
 switchport mode trunk
!
interface GigabitEthernet 0/1
 description to AP1
 switchport mode trunk
 switchport trunk native vlan 30
 poe enable
!
interface VLAN 30
 ip address 192.168.30.15 255.255.255.0
!
! 設定保存
end
wr 

その他DHCPなどの設定はうちでは不要なので消した。(この辺は適宜対応)

AP設定

こちらも同様にコンソールで接続して設定。最低限設定が必要なのはACのIPアドレスと自身のIPアドレスのみ。


conf t
!
acip ipv4 192.168.30.15 
apip ipv4 192.168.30.17 255.255.255.0 192.168.30.1
!
interface BVI 1
 ip address 192.168.30.17 255.255.255.0
!
! 設定保存
end
wr 

接続

これで接続すればACにAPが登録される。WebUIから確認ができ,以降はこちらで操作する。

ひとまず初期設定はこれで完了。無線設定はどうにかなるから省略。

RDO(All-in-One)アップグレード(Queens→Yoga)

そろそろOpenStackの環境を更新しようと。

ここここにならってコンポーネント毎にアップグレードを行っていく。

オフィシャルでは始める前にsytemdのスナップショットをとれとあるが,そんなオプションはないと怒られる・・・。もう廃止されたオプションなのか???ググっても情報見つけられず。

Before updating, take a systemd snapshot of the OpenStack services:

# systemctl snapshot openstack-services
https://www.rdoproject.org/install/upgrading-rdo-1/

とりあえずこの手順を飛ばし,以下流れで進めていく。

  1. OpenStackサービスの停止
  2. アップグレード
  3. DBの同期
  4. OpenStackサービス起動

OpenStackサービスの停止

# systemctl stop 'openstack-*'
# systemctl stop 'neutron-*'
# systemctl stop 'openvswitch'

上記で停止するのは以下ユニット

openstack-aodh-evaluator.service
openstack-aodh-listener.service
openstack-aodh-notifier.service
openstack-ceilometer-notification.service
openstack-ceilometer-polling.service
openstack-cinder-api.service
openstack-cinder-backup.service
openstack-cinder-scheduler.service
openstack-cinder-volume.service
openstack-glance-api.service
openstack-losetup.service
openstack-nova-compute.service
openstack-nova-conductor.service
openstack-nova-novncproxy.service
openstack-nova-scheduler.service
openstack-swift-account-auditor.service
openstack-swift-account-reaper.service
openstack-swift-account-replicator.service
openstack-swift-account.service
openstack-swift-container-auditor.service
openstack-swift-container-replicator.service
openstack-swift-container-sync.service
openstack-swift-container-updater.service
openstack-swift-container.service
openstack-swift-object-auditor.service
openstack-swift-object-expirer.service
openstack-swift-object-reconstructor.service
openstack-swift-object-replicator.service
openstack-swift-object-updater.service
openstack-swift-object.service
openstack-swift-proxy.service
neutron-ovn-metadata-agent.service
neutron-server.service
openvswitch.service

アップグレード

# dnf install -y https://www.rdoproject.org/repos/rdo-release.rpm
# dnf update

DBの同期

# su -s /bin/sh -c "keystone-manage db_sync" keystone
# su -s /bin/sh -c "glance-manage db_sync" glance
# su -s /bin/sh -c "cinder-manage db sync" cinder
# su -s /bin/sh -c "neutron-db-manage upgrade heads" neutron
# su -s /bin/sh -c "nova-manage cell_v2 map_cell0" nova

# su -s /bin/sh -c "nova-manage --config-file /etc/nova/nova.conf cell_v2 create_cell --name=cell1 --verbose" nova
# su -s /bin/sh -c "nova-manage db sync" nova
# su -s /bin/sh -c "nova-manage cell_v2 discover_hosts --verbose" nova
# nova-manage cell_v2 list_cells
# su -s /bin/sh -c "nova-manage cell_v2 map_instances --cell_uuid <cell UUID>" nova
# su -s /bin/sh -c "nova-manage api_db sync" nova

うちの環境特有かもしれないが,httpdもアップグレードされ,デフォルトのssl.confが作成されているので削除。

# rm /etc/httpd/conf.d/ssl.conf

OpenStackサービス起動

再起動して完了。

と,思いきややはりというかエラーで起動しない。

エラー1つめ(nova)

コンピュートのバージョンが古すぎる?

こんなログがnova-scheduler.logに出てNG。

ERROR nova   File "/usr/lib/python3.6/site-packages/nova/utils.py", line 1100, in raise_if_old_compute
 ERROR nova     oldest_supported_service=oldest_supported_service_level)
 ERROR nova nova.exception.TooOldComputeService: Current Nova version does not support computes older than Xena but the minimum compute service level in your system is 56 and the oldest supported service level is 57.

QからYはサポート外なのか???とりあえずutils.pyの1100行目を見てみるとバージョン判定箇所らしい。私の力ではこれ以上解析が無理なので力業でコメントアウト。

1095     if current_service_version < oldest_supported_service_level:
1096 #        raise exception.TooOldComputeService(
1097 #            oldest_supported_version=service.OLDEST_SUPPORTED_SERVICE_VERSION,
1098 #            scope=scope,
1099 #            min_service_level=current_service_version,
1100 #            oldest_supported_service=oldest_supported_service_level)
1101         return

novaはこれで起動したw (今はこれでいいんだ)

エラー2つ目(neutronというかopenvswitch)

openvswichの6642に接続できないというエラーを吐いてNeutronも起動しない。ovn-northd.serviceが起動していなかったので起動したらここはクリアになった。

終わらないトラブル

無事にアップデート前の状態までもっていくことが出来たと思いきや,インスタンスは起動するものの外部ネットワークへ繋がらない問題発生。新しいインスタンスを作成してみるもエラー,既存のインスタンスを削除しようにもエラー。ログを見ると「’c.consumer_type_id という知らない引数が渡されている」的なメッセージが出ていた。ググってみるとどうやらPlacement関連で何か引っかかっている模様。そういえばplacementのDB同期はやっていなかった。ひとまずインスタンスは空にして今の環境で作り直すとする。

必要なインスタンスだけスナップショットをとり,DBから直接インスタンスを削除してから↓。

# placement-manage db sync 

インスタンス作成→失敗・・・orz。インスタンス削除 → 成功 !一歩前進。DB直でいじったからインスタンス割り当たっているけどDBに無いよというエラーメッセージが永遠と出る。対処法はこれ

$ pip install osc-placement       # resourceオプションがなかったから入れる
$ openstack resource provider list   # compute nodeのUUID確認
$ openstack resource provider show --allocations <UUID>  # ServerのUUID確認(念のためエラーメッセージのUUIDと同じか確認)
$ openstack resource provider allocation delete <Server UUID> 

nova周りはさらにエラーは続き,Neutron周りでもエラーが出続ける。

ERROR ovsdbapp.backend.ovs_idl.command [-] Error executing command (DbAddCommand): ovsdbapp.backend.ovs_idl.idlutils.RowNotFound: Cannot find Chassis_Private with name=xxx

色々ググったあげく,Southband側の問題のように見えたのでovs-sbなんたらとかでいじっていると,そもそもSouthband側が機能していないことに気づき,以下で解決した。

# systemctl start ovn-controller.service

アップグレード前と後でサービスの起動ってこんなに違ったかしら・・・・?

要らないと思っていたsystemctlのSnapshot,必要だったかもしれない・・・。

一応すったもんだ丸2日かかったけれど,無事にYogaへアップグレード完了した。

まとまっていないが,何年か後に自分が見直すためのメモとして。

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