Linux上からIPv6アドレス指定でsshするときにはインタフェース名をつける


Linux上からIPv6アドレスを指定してsshしようとしたら「port 22: Invalid argument」と言われてしまった。

[root@centos8 ~]# ssh root@fe80::250:56ff:fe8f:aba9
ssh: connect to host fe80::250:56ff:fe8f:aba9 port 22: Invalid argument
[root@centos8 ~]#

きちんとpingでは応答あるのに

[root@centos8 ~]# ping -6 fe80::250:56ff:fe8f:aba9 -c 5
PING fe80::250:56ff:fe8f:aba9(fe80::250:56ff:fe8f:aba9) 56 data bytes
64 bytes from fe80::250:56ff:fe8f:aba9%ens192: icmp_seq=1 ttl=255 time=0.246 ms
64 bytes from fe80::250:56ff:fe8f:aba9%ens192: icmp_seq=2 ttl=255 time=0.269 ms
64 bytes from fe80::250:56ff:fe8f:aba9%ens192: icmp_seq=3 ttl=255 time=0.250 ms
64 bytes from fe80::250:56ff:fe8f:aba9%ens192: icmp_seq=4 ttl=255 time=0.303 ms
64 bytes from fe80::250:56ff:fe8f:aba9%ens192: icmp_seq=5 ttl=255 time=0.316 ms

--- fe80::250:56ff:fe8f:aba9 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 135ms
rtt min/avg/max/mdev = 0.246/0.276/0.316/0.035 ms
[root@centos8 ~]#

なんでかと思ったら、sshコマンドでは、sshコマンドを実行したホストのどのインタフェースを使ってアクセスするのかを明示的に指定する必要があったようだ。

[root@centos8 ~]# ip a s
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:9c:2a:d1 brd ff:ff:ff:ff:ff:ff
    inet 172.17.44.49/16 brd 172.17.255.255 scope global noprefixroute ens192
       valid_lft forever preferred_lft forever
    inet6 xxxx:xxx:xxxx:4700:2788:3aad:4bfa:6715/64 scope global dynamic noprefixroute
       valid_lft 2172237sec preferred_lft 185037sec
    inet6 fe80::2c85:a948:cd5:d5e1/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
[root@centos8 ~]#

つかうネットワークインタフェースは「ens192」なので、IPv6アドレスの後ろに「%ens192」をつけて実行

[root@centos8 ~]# ssh  root@fe80::250:56ff:fe8f:aba9%ens192
Password:
Last login: Wed Apr  7 16:24:37 2021 from fe80::2c85:a948
Oracle Corporation      SunOS 5.11      11.3    September 2015
root@solaris11:~# exit
logout
Connection to fe80::250:56ff:fe8f:aba9%ens192 closed.
[root@centos8 ~]#

問題無く接続できました。

Solaris11でホスト名/IPアドレスを変更する


Solaris10だったら以下のファイルあたりの変更でやってた

/etc/nodename
/etc/hostname.ネットワークインタフェース名
/etc/hosts
/etc/resolv.conf
/etc/nsswitch.conf

Solaris11だとファイルを編集するのではなく、コマンドで変更する形になる

資料:Oracle® Solaris 10 から Oracle Solaris 11.3 への移行「Oracle Solaris 11 でのネットワークの構成

現在のホスト名確認


ホスト名変更

# svccfg -s svc:/system/identity:node setprop config/nodename=ホスト名
# svcadm refresh svc:/system/identity:node
# svcadm restart svc:/system/identity:node
# vi /etc/hosts で関係するホスト名を修正
# reboot

refreshのところは「svcadm refresh node」でも大丈夫説がある模様

ネットワーク設定確認

ネタ元 IPv4 インタフェースの構成

# ipadm show-addr
# ipadm show-if
# route -p show
# netstat -rn
# dladm show-phys
# dladm show-link

ネットワーク設定変更

現在値を消して、新規作成となるが2種類手順がある

アドレス設定のみ削除するもの

# ipadm delete-addr net?/v4
# ipadm create-addr -T static -a local=<IPアドレス>/<プレフィックス> net?/v4

ネットワーク定義全体を削除するもの

# ipadm delete-ip net?
# ipadm create-ip net?
# ipadm create-addr -T static -a local=<IPアドレス>/<プレフィックス> net?/v4

デフォルトゲートウェイ設定

# route -p add default <IPアドレス>

DNS設定確認

#  svccfg -s network/dns/client
svc:network/dns/client> listprop config
<略>
svc:network/dns/client> quit
#

DNS設定変更

(ネタ元 DNS クライアントを有効にする方法 )

#  svccfg -s network/dns/client
svc:/network/dns/client> setprop config/search = astring: ("<ドメイン名>" "<ドメイン名>")
svc:/network/dns/client> setprop config/nameserver = net_address: (<IPアドレス> <IPアドレス>)
svc:/network/dns/client> setprop config/options = timeout:1 
svc:/network/dns/client> select network/dns/client:default
svc:/network/dns/client:default> refresh 
svc:/network/dns/client> quit
#
# svcadm enable network/dns/client 

nsswitchの設定を確認する場合

# cat /etc/nsswitch.conf
# svccfg -s system/name-service/switch 
svc:/system/name-service/switch> listprop config
<略>
svc:/system/name-service/switch> quit
#

nsswitchを変更する場合の例

# svccfg -s system/name-service/switch 
svc:/system/name-service/switch> setprop config/host = astring: "dns files [TRYAGAIN=0]" 
svc:/system/name-service/switch> select system/name-service/switch:default 
svc:/system/name-service/switch:default> refresh 
svc:/system/name-service/switch:default> quit
# svcadm enable system/name-service/switch 
# svcadm refresh name-service/switch

Oracle公式に書いてあるDNSサーバ設定手順例

# svccfg -s dns/client setprop config/nameserver=net_address: 192.168.1.1
# svccfg -s dns/client setprop config/domain = astring: "foohost.org"
# svccfg -s name-service/switch setprop config/host = astring: "files dns"
# svcadm refresh name-service/switch
# svcadm refresh dns/client

rootユーザのログイン拒否問題

telnet は /etc/default/login の「CONSOLE=/dev/console」をコメントにする

sshは/etc/ssh/sshd_configに「PermitRootLogin yes」を設定して「svcadm restart ssh」

2段階のNFSマウントをする方法


直接アクセスできないネットワークにあるNFSサーバをNFSでマウントすることはできないか試行錯誤してみた。

普通にCentOS7やSolaris11からやってみたところ、NFSマウントした領域のNFS exportでの公開はnfsd側から「Cannot export /mnt, possibly unsupported filesystem or fsid= required」とか、「Invalid filesystem」とか言われて設定できない。

これはuser-spaceで動作するnfsdを使えば回避できるんじゃないかと探してみた結果、unfs3というものを発見。ソースコードは https://github.com/unfs3/unfs3

Linux,FreeBSD,Solaris,AIX,Irix,MacOSXで動く以外に、Windows上でも制限ありで動作するとのこと。

Windows上で動かした場合は、unfsdが使用するWindowsユーザを1つ割り当てる形になるので、NFS経由のアクセスは全てそのWindowsユーザがアクセスしている、という扱いになるようだ。

あと、このunfs3はNFS ver3のみ使え、NFS v4やNFS v2でのアクセスには対応していない。また、NFS v3でもREADDIRPLUS(属性付きディレクトリの読み取り)周りは実装していないとのこと。

READDIRPLUSはOracle/Solarisのドキュメントによればlsコマンドなどでディレクトリ内のファイル一覧を表示させる動作を高速化するためのものなので、まぁ、なくてもなんとかなる感じのもの。

属性付きディレクトリの読み取り
NFS バージョン 3 では、READDIRPLUS と呼ばれる操作があります。たとえば、ls や ls -l などの、大部分の READDIR が READDIRPLUS コールとして発行されます。バージョン 3 で ls -l コマンドを実行すると、ディレクトリ内の名前リストと共に、ファイルハンドルと属性が返されます。バージョン 2 では、名前が最初に返され、ファイルハンドルと属性を取得するには、続いてサーバーを呼び出す必要があります。
バージョン 3 の READDIRPLUS 操作の利点は、ファイルごとに GETATTR 要求を送信する必要がないため時間が短縮され、ls と ls -l の速度が同程度になることです。

要件は満たせそうなので、とりあえずテスト用CentOS7環境でunfs3を動作させてみる。

準備

環境をインストール

# yum install git
# yum groupinstall "開発ツール"

コンパイル

まず、ソースコードの入手

$ git clone https://github.com/unfs3/unfs3.git

READMEにあるとおりbootstrap&configureを実行

$ cd unfs3/unfs3
$ ./bootstrap
$ ./configure

そしてmake

$ make
for i in Config ; do (cd $i && make all) || exit; done
make[1]: ディレクトリ `/root/unfs3/Config' に入ります
gcc -g -O2 -Wall -W -I.. -I. -I..   -c -o lex.yy.o lex.yy.c
gcc -g -O2 -Wall -W -I.. -I. -I..   -c -o y.tab.o y.tab.c
ar crs lib.a lex.yy.o y.tab.o
make[1]: ディレクトリ `/root/unfs3/Config' から出ます
gcc -g -O2 -Wall -W  -D_GNU_SOURCE -I.   -c -o afsgettimes.o afsgettimes.c
gcc -g -O2 -Wall -W  -D_GNU_SOURCE -I.   -c -o afssupport.o afssupport.c
gcc -g -O2 -Wall -W  -D_GNU_SOURCE -I.   -c -o attr.o attr.c
attr.c: 関数 ‘get_free_bad_dir_entry’ 内:
attr.c:550:5: エラー: ‘for’ ループ初期化宣言は C99 モード内でのみ許可されてい ます
     for (int i = 0;i < BAD_DIR_CACHE_SIZE;i++) {
     ^
attr.c:550:5: 備考: オプション -std=c99 または -std=gnu99 をコードコンパイル時に使用してください
attr.c: 関数 ‘find_bad_dir_entry’ 内:
attr.c:573:5: エラー: ‘for’ ループ初期化宣言は C99 モード内でのみ許可されてい ます
     for (int i = 0;i < BAD_DIR_CACHE_SIZE;i++) {
     ^
make: *** [attr.o] エラー 1
$

エラーとなってしまいます。

これはコンパイル時のオプションに「-std=c99」を指定するようにして解決

$ export CPPFLAGS="-std=c99";./configure
$ make
<略>
$

インストールと設定

普通にmake installすると/usr/local以下にインストールされます。

# make install
/usr/bin/install -c -d /usr/local/sbin
/usr/bin/install -c -d /usr/local/share/man/man7
/usr/bin/install -c -d /usr/local/share/man/man8
/usr/bin/install -c unfsd /usr/local/sbin/unfsd
/usr/bin/install -c -m 644 ./Extras/tags.7 /usr/local/share/man/man7/tags.7
/usr/bin/install -c -m 644 ./unfsd.8       /usr/local/share/man/man8/unfsd.8
#

NFSで公開するディレクトリの設定は、普通のnfsdと同じく /etc/exports ファイルを使用。「-e」オプションで別のファイルを指定することも可能です。

注意点としては、Linuxだとホスト名指定に「*」とnetgroupが使用できず、ログに「unfsd[20479]: syntax error in ‘/etc/exports’, exporting nothing」といった出力が出てしまうという点です。

「*」については「0.0.0.0/0」で代替できます。

/etc/exports ファイルを編集した場合、変更にはexportfsコマンドは使用できません。

unfsdに対してHUPシグナルを送ることで反映されます。(kill -HUP unfsdのPID)

unfsdの起動は「/usr/local/sbin/unfsd」の実行、停止はunfsdへのTERMシグナル送信(kill -TERM unfsdのPID)です。

Solaris 11をNISクライアントにする


Solaris 環境からのNFS v4アクセスを確認するため、VMware上にSolaris 11をインストールした。

NISによるユーザIDの共通化も検証するため、NISクライアントの設定を行った。

NISクライアントにする設定は「domainname NISドメイン名」でNISのドメイン名を設定したあと「ypinit -c」で終わり。

つぎは/etc/nsswitch.confを編集して…と思ってvi /etc/nsswitch.confで開いてみると、手動で編集するな、という記載が…

マニュアルを探すと「Oracle Solaris 11.1 でのネームサービスおよびディレクトリサービスの作業」の「ネームサービススイッチの管理」があった。

「データベースのソースを切り替える方法」にある「svccfg -s system/name-service/switch」で入ったあと「listprop config」で現在の設定値を確認できる。

nsswitch.conf にあるいろんなエントリのうち、hostsとprinterしかない。

じゃぁ、手動で設定すればいいのかと「setprop config/passwd=”files nis”」と実行してみるとエラー。

じゃぁ、と「setprop config/password=”files nis”」に変えてみると設定成功

「setprop config/group=”files nis”」も実行。

「quit」で抜けて、「svcadm refresh name-service/switch」を実行するとシステムに反映されて、ls -l でみた場合の結果に反映された。

また、値が反映されると/etc/nsswitch.confの内容も書き換わる。