promisc
mac mini
Windows 11が発表された。リーク通りのネタにお墨付きを与えた格好。 Windows 11 のシステム要件、機能、デバイスの要件について 今回は、こんなおまけも付くらしい。やっぱり世間で流行っているものは、取り入れておかんとなって事だ。 Windows 11ではAndroidアプリが動作
こんなのやだってんで、ラズパイを調べてみたんだけど、それをもっと頑丈にした、弁当箱がアプルから発売されてる。Mac miniですって。ミニと言う割には、巨人用の箱だな。
Mac miniと言えば、BSD系のOS。そんなのやだって言うリナ族も居る訳で。そんな人達が喜びそうなエミュレータが紹介されてた。 UTMを使ってM1 Mac上でUbuntuを動かす
オイラーは軽く動くやつが欲しいぞ。Debian 11 のメジャーデビューは何時だ?
T型コネクタ
T型コネクタ なんてのを思い出しちゃぞ。モノタロウでも買えるのね。ああ、エレキ知らない人に説明すると、teeね。尚更分からないか。
信号線の途中から、信号を取り出す為のタッピングコネクタね。スパイ御用達。昔よくお世話になった。懐かしいな。 wiresharkでUSBのパケットを盗聴出来るなんて書いたものだから、連想記憶が発動したのさ。
とあるBUSラインを盗聴出来るように、タッピング装置を自作した事が有るぞ。 流れる信号をデコードしないと、扱い辛い。そこで、出入りのソフト屋さんに頼んで、コードを書いて貰った。
ハード一式はこちらにしかないので、debugは弊社内で。Linuxは何使ってますって聴いたら、Plamo Linux ですって言われたんで、用意した覚えがある。 シンプルでよかったな。
kill -9 at OpenBSD
前回の続き、tcpdumpを動かしておいて、それをkill -9で即死させた時、ちゃんとpromiscモードはクリアされてた。tcpdumpの特殊性ゆえに、考慮されているのかな? そんなのコード嫁。でもいいんだけど、基本は簡単な物を調べる、です。
こんな事もあろうかと、mypc.cを作っておいた。こいつを動かしておいて、有無を言わさず即死させたらどうなる? 考えていてもしょうがないので、カーネルを追跡。
(gdb) bt #0 ifpromisc (ifp=0xd184b030, pswitch=0) at /usr/src/sys/net/if.c:2928 #1 0xd0d7b09b in bpf_detachd (d=0xd1875d00) at /usr/src/sys/net/bpf.c:323 #2 0xd0d7b42f in bpfclose (dev=136960, flag=3, mode=8192, p=0xd168518c) at /usr/src/sys/net/bpf.c:390 #3 0xd07aea58 in spec_close_clone (ap=0xf1d49948) at /usr/src/sys/kern/spec_vnops.c:769 #4 0xd07acbe9 in spec_close (v=0xf1d49948) at /usr/src/sys/kern/spec_vnops.c:503 #5 0xd057a98c in VOP_CLOSE (vp=0xf1d11900, fflag=3, cred=0xd17f4c60, p=0xd168518c) at /usr/src/sys/ker\ n/vfs_vops.c:174 #6 0xd03689e0 in vn_close (vp=0xf1d11900, flags=3, cred=0xd17f4c60, p=0xd168518c) at /usr/src/sys/kern\ /vfs_vnops.c:301 #7 0xd0367e9f in vn_closefile (fp=0xd1683620, p=0xd168518c) at /usr/src/sys/kern/vfs_vnops.c:613 #8 0xd03887e1 in fdrop (fp=0xd1683620, p=0xd168518c) at /usr/src/sys/kern/kern_descrip.c:1273 #9 0xd038ad35 in closef (fp=0xd1683620, p=0xd168518c) at /usr/src/sys/kern/kern_descrip.c:1257 #10 0xd038bd22 in fdfree (p=0xd168518c) at /usr/src/sys/kern/kern_descrip.c:1196 #11 0xd070b001 in exit1 (p=0xd168518c, rv=9, flags=1) at /usr/src/sys/kern/kern_exit.c:194 #12 0xd0a0e197 in sigexit (p=0xd168518c, signum=9) at /usr/src/sys/kern/kern_sig.c:1499 #13 0xd0a0ed6c in postsig (p=0xd168518c, signum=9) at /usr/src/sys/kern/kern_sig.c:1431 #14 0xd0a0fe35 in userret (p=0xd168518c) at /usr/src/sys/kern/kern_sig.c:1890 #15 0xd06baedd in mi_syscall_return (p=0xd168518c, code=3, error=-1, retval=0xf1d49d0c) at /usr/src/sys\ /sys/syscall_mi.h:112 #16 0xd06babc7 in syscall (frame=0xf1d49d50) at /usr/src/sys/arch/i386/i386/trap.c:619 #17 0xd09afd1d in Xsyscall_untramp () #18 0xf1d49d50 in ?? () #19 0x03682175 in ?? () Backtrace stopped: previous frame inner to this frame (corrupt stack?)
Ctl-c でも、ほぼ同様なコースを辿り、promiscはクリアされてた。出来の悪いSIGに反応しないプログラムを書いても、ちゃんと後始末をしてくれている。素晴らしい!
FreeBSDでも、同じ挙動になったよ。さすがBSD族だ。
about Linux
NICがpromiscモードになってる指標としてifconfigのstatusに出て来るそれを目印にしてた。リナでは、それが表われないんだ。
なんてやると、確かに現れるけどね。tcpdumpしてる状態では出てこない。そこで自作のmypc.cですよ。構造が簡単だからgdbで追い易い。これ、オイラーの昔からの流儀ね。
オシロスコープで波形を調べる時、まれにしか表われない波形を観測する為、輝度を上げ、回りの光を遮光する為、昔の写真屋さんのように、作業服をオシロに被せて観測してる人を散見した。オイラーこういうの苦手。 波形を観測し易いように、プログラムを組み替えて、悠悠とオシロを眺めたものだ。こうでなくっちゃね。
自前でコンパイルしたlibpcapを組み込んで、 LD_LIBRARY_PATH を設定して、いざ出陣。
(gdb) bt #0 pcap_activate_linux (handle=0x405590) at ./pcap-linux.c:961 #1 0xb7f911f7 in pcap_activate (p=0x405590) at ./pcap.c:2721 #2 0xb7f91766 in pcap_open_live (device=0xbffff59d "wlp5s0", snaplen=4096, promisc=1, to_ms=1000, errbuf=0xbffff5a4 "R\t") at ./pcap.c:2847 #3 0x00401430 in main () at mypc.c:50
ちまちまとソースを見て行ったら、 /sys/class/net/IFname あたりを見ておくと良いかも。check at debian(64)
root@pen:/sys/class/net/ens33# ifconfig ens33
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
:
root@pen:/sys/class/net/ens33# ifconfig ens33 promisc
root@pen:/sys/class/net/ens33# ifconfig ens33
ens33: flags=4419<UP,BROADCAST,RUNNING,PROMISC,MULTICAST> mtu 1500
:
これに対応して、目星を付けたデータは、下記のように変化した。
sakae@pen:/sys/class/net/ens33$ cat flags 0x1003 sakae@pen:/sys/class/net/ens33$ cat flags 0x1103
/usr/include/net/if.h
IFF_UP = 0x1, /* Interface is up. */ IFF_BROADCAST = 0x2, /* Broadcast address valid. */ IFF_RUNNING = 0x40, /* Resources allocated. */ IFF_PROMISC = 0x100, /* Receive all packets. */ IFF_MULTICAST = 0x1000, /* Supports multicast. */
動かぬ証拠だな。
もう一つ、バグっぽいの。tcpdumpでずっとpromiscにしておき、flagとかを確認
sakae@pen:/sys/class/net/ens33$ cat flags 0x1103 sakae@pen:/sys/class/net/ens33$ /sbin/ifconfig ens33 ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 :
ちゃんとフラグは立っているのに、ifconfigではそれが見えず。これって、悪い人の盗聴を助長するしかけだな。でも、良心は残っているようで、kill -9 で、突然死させると、該当のflagは落ちたよ。rootさんは、怪しげな盗聴を発見したら、迷わずプロセスを殺しましょう。
これでお終いにしてもいいんだけど、いまいちすっきりしない。NICの石のflagにpromiscが反映されない点。詳細は以前にやったuftraceとかを走らせれば判明するだろうと軽く考えた。
まて、もっとお手軽な誰でも出来る方法があるぞ。
root@pen:/tmp# strace -o LOG tcpdump port 8080 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes ^C 0 packets captured 0 packets received by filter 0 packets dropped by kernel
systemcallのログを取得。そして
sakae@pen:/tmp$ grep ioctl LOG | grep ens33
ioctl(3, SIOCGIFHWADDR, {ifr_name="ens33", ifr_hwaddr={sa_family=ARPHRD_ETHER, sa_data=00:0c:29:4d:18:2d}}) = 0
ioctl(3, SIOCGIFINDEX, {ifr_name="ens33", }) = 0
ioctl(4, SIOCGIFFLAGS, {ifr_name="ens33", ifr_flags=IFF_UP|IFF_BROADCAST|IFF_RUNNING|IFF_MULTICAST}) = 0
ioctl(3, SIOCGIFHWADDR, {ifr_name="ens33", ifr_hwaddr={sa_family=ARPHRD_ETHER, sa_data=00:0c:29:4d:18:2d}}) = 0
ioctl(3, SIOCGIFINDEX, {ifr_name="ens33", }) = 0
NICの設定をノーマルに戻しているのは引っかかってきた。けど、セットの現場は発見できず。LOGを精査する。
setsockopt(3, SOL_PACKET, PACKET_ADD_MEMBERSHIP, {mr_ifindex=if_nametoindex("ens33"), mr_type=PACKET_MR_PROMISC, mr_alen=0, mr_address=}, 16) = 0
どうやら、これっぽい。setsockoptってのは、systemcallの一員なのね。
pcap-linux.c/activate_pf_packet
/*
* Hmm, how can we set promiscuous mode on all interfaces?
* I am not sure if that is possible at all. For now, we
* silently ignore attempts to turn promiscuous mode on
* for the "any" device (so you don't have to explicitly
* disable it in programs such as tcpdump).
*/
if (!is_any_device && handle->opt.promisc) {
memset(&mr, 0, sizeof(mr));
mr.mr_ifindex = handlep->ifindex;
mr.mr_type = PACKET_MR_PROMISC;
if (setsockopt(sock_fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
&mr, sizeof(mr)) == -1) {
pcap_fmt_errmsg_for_errno(handle->errbuf,
PCAP_ERRBUF_SIZE, errno, "setsockopt (PACKET_ADD_MEMBERSHIP)");
close(sock_fd);
return PCAP_ERROR;
}
}
どうやら、これっぽい。それにして、何でリナにpfなんて語句が出て来るの? なんか裏道っぽい事をやってる雰囲気。だから、正統なifconfigでは、表に出てこないのか。
/usr/include/linux/if_packet.h に、こんな定義が有った。これってリナ専用のNICの裏仕様書だな。得意の速く動けば良い。それには、パケットをあちこち引き回すんじゃなくて、nmapで処理しちゃえ。それで、新たな枠組みが必要ですって事か。
#define PACKET_MR_MULTICAST 0 #define PACKET_MR_PROMISC 1 #define PACKET_MR_ALLMULTI 2 #define PACKET_MR_UNICAST 3
ifconfig.c
リナでpromiscをどうやってセットしてるか? 昔堅気のオイラーは、net-tools/ifconfig.cなんてのを参照してみた。
if (!strcmp(*spp, "promisc")) {
goterr |= set_flag(ifr.ifr_name, IFF_PROMISC);
spp++;
continue;
}
if (!strcmp(*spp, "-promisc")) {
goterr |= clr_flag(ifr.ifr_name, IFF_PROMISC);
if (test_flag(ifr.ifr_name, IFF_PROMISC) > 0)
fprintf(stderr, _("Warning: Interface %s still in promisc mode.\
.. maybe other application is running?\n"), ifr.ifr_name);
spp++;
continue;
}
こんなのが書いてあった。そして、呼び出しているのは、
/* Set a certain interface flag. */
static int set_flag(char *ifname, short flag)
{
struct ifreq ifr;
safe_strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) {
fprintf(stderr, _("%s: ERROR while getting interface flags: %s\n"),
ifname, strerror(errno));
return (-1);
}
safe_strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
ifr.ifr_flags |= flag;
if (ioctl(skfd, SIOCSIFFLAGS, &ifr) < 0) {
perror("SIOCSIFFLAGS");
return -1;
}
return (0);
}
現状のステータスと言うか、コントロールワードを石から読み込み、それに新たなBITをORして、書き戻している。極めて真っ当なやり方だ。これなら、ちゃんと石の現状を表現してる。
それに対して、libpcapで使われている手法は、石の特性を無視して、隠れて操作しているな。 何だか、2枚舌みたいで、気持ち悪い。まあ、リナは動けばOKってのがデフォだからなあ。
slattach.c
net-toolsの面白いものを発見。前回ちょいと言及したslipだ。
SLATTACH(8) Linux System Administrator's Manual SLATTACH(8)
NAME
slattach - attach a network interface to a serial line
SYNOPSIS
slattach [-dehlLmnqv] [-c command] [-p proto] [-s speed] [tty]
DESCRIPTION
Slattach is a tiny little program that can be used to put a normal ter‐
minal ("serial") line into one of several "network" modes, thus allow‐
ing you to use it for point-to-point links to other computers.
こんなものが残っていたとは。ifconfigは最近では推奨されないって事だけど、古い物を捨て去る風潮だな。こういう歴史を抹殺してく訳だ。まあ、今のパソコンにRS232CのI/Fなんて付いていないから、このコマンドが残っていても使い道は、ないだろうけど。
有効に使えたのは、モデムを付けて、パソコン通信してた時代までです(それって、昭和の時代だからね)。
pcap-filter
いい加減リナに秋田んで、OpenBSDのtcpdumpのツリーを見てる。そしたら、面白いやつを発見。tcpdumpでパケットをフィルターするのはpcapに丸投げしてるんだ。そして、そのフィルターの書式が
PCAP-FILTER(5) File Formats Manual PCAP-FILTER(5)
NAME
pcap-filter – packet filter syntax
DESCRIPTION
pcap_compile(3) compiles pcap filters for software such as tcpdump(8).
The resulting filter program can then be applied to some stream of
packets to determine which packets will be supplied to pcap_loop(3),
pcap_dispatch(3), pcap_next(3), or pcap_next_ex(3).
:
pcapを使った極小のやつにも、pcap-compileが出て来た。コンパイルしてるのか。そしてコンパイル結果は、tcpdumpで確認出来るとな。
ob# tcpdump -d ip (000) ldh [12] (001) jeq #0x800 jt 2 jf 3 (002) ret #116 (003) ret #0 ob# tcpdump -d tcp (000) ldh [12] (001) jeq #0x86dd jt 2 jf 4 (002) ldb [20] (003) jeq #0x6 jt 7 jf 8 (004) jeq #0x800 jt 5 jf 8 (005) ldb [23] (006) jeq #0x6 jt 7 jf 8 (007) ret #116 (008) ret #0
最初のフィルターは、ipだけ通してね。次のフィルターはtcpなパケットだけを通してねって指示だ。何となく分かるような気がする。
最初のやつだと、パケットの12番目のデータが0x800なら、それはIPパケットですって読める。 それはいいんだけど、この翻訳された超ミニ言語を実行する機構が必要だな。
ひょっとして bpf(4)
Filter machine
A filter program is an array of instructions with all branches forwardly
directed, terminated by a “return” instruction. Each instruction
performs some action on the pseudo-machine state, which consists of an
accumulator, index register, scratch memory store, and implicit program
counter.
The following structure defines the instruction format:
struct bpf_insn {
u_int16_t code;
u_char jt;
u_char jf;
u_int32_t k;
};
この後に例が沢山出て来てる。一方tcpdumpのオプションをちょいとC語風に表示するように指示してみた。なんか、bpfの説明と符合してるね。
ob# tcpdump -dd ip
{ 0x28, 0, 0, 0x0000000c },
{ 0x15, 0, 1, 0x00000800 },
{ 0x6, 0, 0, 0x00000074 },
{ 0x6, 0, 0, 0x00000000 },
そして動かぬ証拠を掴んだ。 libpcap/bpf_image.c
case BPF_LD|BPF_W|BPF_ABS:
op = "ld";
fmt = "[%d]";
break;
case BPF_LD|BPF_H|BPF_ABS:
op = "ldh";
fmt = "[%d]";
break;
case BPF_LD|BPF_B|BPF_ABS:
op = "ldb";
fmt = "[%d]";
break;
case BPF_JMP|BPF_JEQ|BPF_K:
op = "jeq";
fmt = "#0x%x";
break;
:
BPFのコマンドをlibpcap流の表記で印字する、逆アセンブラーなんだな。