Logo address

Mac /etc/hosts の怪

2023/11/16

Host Database

host database とは ホスト名と IP アドレスを対応付けるデータベースである。
インターネットの通信は、基本を辿れば IP アドレスである。ところが IP アドレスは数字の列であって、人には優しくない。そこで IP アドレスではなくて名前でアクセスできるよう、名前を基に IP アドレスを知らせてくれるサービスが現れた。このへんの事情は、電話番号では相手を覚えられないので、電話帳がサービスされているのと同じである。
ホストが名前を持ち、名前から IP を検索できるシステムは DNS(Domain Name System)と呼ばれる。IP アドレスがインターネットの世界で一意性が要求されるのと同様にホスト名もインターネットの世界で一意性が要求される。従って世界的な大掛かりなデータベースシステムである。
インターネットと完全に隔離された世界では、そこで何をしようと迷惑をかけるわけではない。従って基本的に勝手で良いのであるが、家庭内のネットワークは完全隔離ではなくインターネットの世界とは半透膜で仕切られている。基本的な考え方は外部から内部へのアクセスは遮断され、内部から外部へのアクセスは自由である。詳細は home gateway の設定で決まる。インターネットの契約をすると home gateway が設置されるが、普通の家庭を想定して初期設定されている。何もしなくても不自由なく平和に暮らせるように。
普通でない家庭とは、我家のようにインターネットサーバーが存在する家庭である。この場合には特殊なニーズが存在する。
home gateway の設定が要求されるが、この問題に関しては、ここでは述べない。ここでは我家のサーバーに対して我家の他のコンピュータからアクセスするための DNS に相当する情報をどのように設定するかだけを問題にする。

参考文献

[1] Stephen A.Rago:「詳解 UNIX ネットワークプログラミング」
[2] Cricket Liu, Paul Albits:「DNS & BIND」

/etc/hosts

我家を例に具体的に話をしよう。インターネットの web page ar.nyx.link をサービスしているのはホスト名 ar のサーバーである。

unix 系のクライアントの host database は

/etc/hosts
MacOS ではこの /etc は
/private/etc
にリンクされている。従って
/private/etc/hosts
と言ってもよい。

注意: mbook (我が MacBook)

/etc/netconfig	存在しない (p.236 by Rago)
/etc/inet/hosts	存在しない (p.236 by Rago)
/etc/inet/services	存在しない (p.236 by Rago)
/etc/networks	何してる? --> look NETWORKS(5)
/etc/resolv.conf *1

注 *1: 現在の内容は

#
# This file is automatically generated.
#
nameserver 192.168.0.1
nameserver 192.168.0.1
で、これは「システム環境設定」から入った DNS 設定の内容である。
なお 192.168.0.1 は home gateway で、この DNS サービスには home network の host 例えば ar や ar.local に関する情報は無い。

Mac の場合 DNS server の設定は

システム環境設定 > ネットワーク
そしてネットワーク名を選び
「詳細」
DNS > DNSサーバ

ここから我がMacBook(以下 mbook)で利用する DNS サーバを設定できる。
現在は

192.168.0.1	(home gateway)
だけにしている。
この内容は /etc/resolv.conf にコピーされている。

以前は DNS サーバを自分で運用して、それを mbook に登録していたが、調べてみると DNS サーバへのアクセスが必要以上に多い。

次に示すのは、その時のアクセス記録の一部である。(実際には膨大な量である)
hera は我が DNS サーバである。(OS は Plan9)

hera Nov  4 14:59:57 server: unsupported request 65 from 192.168.0.249
hera Nov  4 15:09:56 server: unsupported request 65 from 192.168.0.249
hera Nov  4 15:29:28 server: unsupported request 65 from 192.168.0.249
hera Nov  4 15:39:56 server: unsupported request 65 from 192.168.0.249
hera Nov  4 15:59:32 server: unsupported request 65 from 192.168.0.249
hera Nov  4 16:09:56 server: unsupported request 65 from 192.168.0.249
hera Nov  4 16:29:08 server: unsupported request 65 from 192.168.0.249
hera Nov  4 16:39:56 server: unsupported request 65 from 192.168.0.249
hera Nov  4 16:59:31 server: unsupported request 65 from 192.168.0.249
request 65 とは何か? 65 はプロトコル番号である。
Plan9 のネットワークデータベース /lib/ndb/common には
protocol=sat-expak	ipv4proto=64
protocol=kryptolan	ipv4proto=65
protocol=rvd		ipv4proto=66
と書かれている。"krypto" は "crypto" のスペルミスかもと思ったが
https://datatracker.ietf.org/doc/html/rfc1700
には
65 KRYPTOLAN Kryptolan [PXL1]
となっている。なお、この情報は mbook の /etc/protocols にも載っている:
ip	0	IP		# internet protocol, pseudo protocol number
#hopopt	0	HOPOPT		# hop-by-hop options for ipv6
icmp	1	ICMP		# internet control message protocol
igmp	2	IGMP		# internet group management protocol
ggp	3	GGP		# gateway-gateway protocol
ipencap	4	IP-ENCAP	# IP encapsulated in IP (officially ``IP'')
st2	5	ST2		# ST2 datagram mode (RFC 1819) (officially ``ST'')
tcp	6	TCP		# transmission control protocol
cbt	7	CBT		# CBT, Tony Ballardie <A.Ballardie@cs.ucl.ac.uk>
egp	8	EGP		# exterior gateway protocol
...
sat-expak	64	SAT-EXPAK	# SATNET and Backroom EXPAK
kryptolan	65	KRYPTOLAN	# Kryptolan
rvd	66	RVD		# MIT Remote Virtual Disk Protocol

コードの該当場所を調べると、先のメッセージはここから来ている:

/sys/src/cmd/ndb/dnserver.c:47: 		dnslog("server: unsupported request %s from %I",

ここには

RR types; see: http://www.iana.org/assignments/dns-parameters
とコメントされている。調べると、
https://ja.wikipedia.org/wiki/DNSレコードタイプの一覧
には
タイプ: HTTPS
値(10進): 65
RFS定義: IETF ドラフト
説明: HTTPS 割り当て
機能: RR that improves performance for clients that need to resolve many resources to access a domain. More info in this IETF Draft by DNSOP Working group and Akamai technologies.
となっている。ドラフトレペルのもので、Plan9(9front) ではサポートされていない。
Apple も新しいものが好きだね。新しいものが出てくると見境もなく飛びつく。しかも DNS 情報の変更が少しでも早くクライアントに伝わった方が喜ばれると考えているのでしょうね。我家では DNS 情報などはめったに変更されないのに。こちらは迷惑。個人環境のDNS情報はクライアントが自分で保持したほうが良いとの結論に至った。

我が環境で問題になっているのは、home network に繋がっているごく少数のサーバーの IP 情報である。クライアントが個別に情報を持てば足りることで、この場合には昔ながらの /etc/hosts の方が良く似合う。
ところがこれに登録しても何だか変なのだ。

/private/etc/hosts

##
# Host Database
#
# localhost is used only to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1       localhost
255.255.255.255 broadcasthost
::1             localhost
fe80::1%lo0	localhost
192.168.0.7	hera
192.168.0.7	ar
192.168.0.7	ar.local
192.168.0.7	ar.nyx.link
注意: 以下の話に関係するものだけを抜き出している

次の mbook 上の実験で見るように "ar.local" の IP "192.168.0.7" を手に入れるのに異常に時間が掛かっている。
なんで~~???

mbook$ time ping -c 1 ar.local
PING ar.local (192.168.0.7): 56 data bytes
64 bytes from 192.168.0.7: icmp_seq=0 ttl=255 time=4.343 ms

--- ar.local ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 4.343/4.343/4.343/0.000 ms

real	0m5.020s
user	0m0.004s
sys	0m0.005s
mbook$ time ping -c 1 ar
PING ar (192.168.0.7): 56 data bytes
64 bytes from 192.168.0.7: icmp_seq=0 ttl=255 time=4.298 ms

--- ar ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 4.298/4.298/4.298/0.000 ms

real	0m0.017s
user	0m0.004s
sys	0m0.005s
mbook$

mbook$ time ping -c 1 192.168.0.7
PING 192.168.0.7 (192.168.0.7): 56 data bytes
64 bytes from 192.168.0.7: icmp_seq=0 ttl=255 time=1.847 ms

--- 192.168.0.7 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 1.847/1.847/1.847/0.000 ms

real	0m0.012s
user	0m0.004s
sys	0m0.005s
mbook$ time ping -c 1 ar.local
PING ar.local (192.168.0.7): 56 data bytes
64 bytes from 192.168.0.7: icmp_seq=0 ttl=255 time=4.663 ms

--- ar.local ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 4.663/4.663/4.663/0.000 ms

real	0m5.019s
user	0m0.004s
sys	0m0.006s
mbook$
この実験によると ar192.168.0.7 への ping は殆ど瞬間的に終わるのに対して ar.local へのアクセスは5秒ほども掛かっている。この傾向は ping だけではなくて、他のツール(curl etc)に対しても一般的なのである。この「5秒」は IP アドレスを DNS に問い合わせるときに返事を待つためのタイムリミットであるとどこかの本に書いてあったが、いまはその箇所を見つけられない。

ブラウザはどうか?
mbook 上には3つのブラウザが動いている

Safari
Chrome
Firefox
どのブラウザでも
http://ar/
http://ar.local/
へアクセスできるが ar.local の方は遅い(5秒ほど遅れる)。何故か?

どのようにして arar.local の IP を知り得たか?
これらの情報はサーバー hera と mbook は保持している。

実行時間の測定に使われたソフトウェアは mbook から実行されているので mbook は自分が保有している情報を自分の生成 process に提供できる。従って arar.local の IP アドレスを実行時に提供可能なのである。こちらはそれを期待して /etc/hosts に情報を書き込んでいるのである。ところが Apple は ar.local の IP は mDNS を使って処理しなくてはならないと考えたのだね...。簡単に /etc/hosts から提供できるのに... なんでわざわざ複雑な方法で? ちなみに Linux ではそのような問題は発生していない。

mDNS (multicast DNS)

今となれば昔の話であるが ar.local の "local" は multicast DNS として予約された。これによって "local" はインターネットのアドレスとして正式に使えなくなった。もっとも皆さんは、LAN の中で使う domain 名に "local" を添えていたと
思う。僕もそうだけど。
今回の実験で、あっと驚いたのはブラウザに与える URL を "http:ar" としても拒否されないのである。僕の記憶では昔は拒否されたと思う。"ar" は domain name ではありませんよって。そこで仕方なく domain name らしくするために "ar.local" としてシステムを設計していたのである。sysname "ar" のまま使えるとすればありがたい話である。

Domain Name の怪

文書を読んでも domain name については解らないことが多い。例えば次の有名な domain name amazon.com について考えてみよう。誰かが amazon.com と紛らわしい名前を登録しようとする。例えば

(a1) amazon.com.
(a2) amazon..com
これらは(文法的に)正しい domain name なのか否か?
(a1) は正しい domain name であり FQDN(Fully Qualified Domain Name) と呼ばれる。問題なのは、(a1) は amazon.com の正式の domain name なのか否かである? 実験によれば mbook で動いている3つのブラウザのどれも
amazon.com.
amazon.com として認識しない。

(a2) の amazon..com は多分 domain name のシンタックスとして許容されない。しかしブラウザによって対応が異なっている。

URL に使われる "domain name" の何たるか解らなくなったのは、"FQDN" あたりからである。我が家の環境ではブラウザから http://ar/ でアクセスできているが、この "ar" は sysname なのか、それとも何かの相対ドメイン名なのか? 相対ドメイン名が URL で許されるなら、セキュリティ問題が発生しないか? 本当に解らなくなりますね。

Apple の mDNS 対応

mbook は ar.local の情報を持っているのだから、自分の子 process から ar.local の IP 情報を要求されたときに素直に渡せばよいのである。Linux で同じことを実験しても ar.localar では実行時間に差はない。つまり Linux は常識的に対応しているのである。ところが Apple は新しいことが大好きである。そこでわざわざ mDNS で対処する。もちろん、現状では大抵の場合にはうまく行かない。つまり「教えて」と LAN 内に大声をかけても、どのサーバーも反応しない。しかしいつまでも反応を待つわけには行かないので、5秒ほど待って諦めて手持ちの情報を子 process に渡していると考えられる。

補充

この辺の話はもっとよく調べること。解ったらまた補足する。
unix のソースコードが欲しい。Mac も Linux もダメ。ソースコードは FreeBSD の方が充実している。

ソケット通信
PF_UNIX: 1つのホストの中で実行されているプロセス間の通信
多分、ここから出発。
現在では IP 通信の中で位置づけられている。
PF_LOCAL(=PF_UNIX)、PF_INET、PF_INET6、etc
ref. SOCKET(2)

     #include <sys/socket.h>

     int
     socket(int domain, int type, int protocol);

socket(PF_LOCAL,SOCK_STREAM,tcp)

/Users/arisawa/dist/p9git-2021
lib9/dial.c:13

IPv4アドレス 224.0.0.251 または IPv6アドレス ff02::fb
UDP port 5353