xinetdを使わずproftpdをtcp wrapper (like)でアクセス制御する

今までproftpd単体ではtcpwrapper使えない思い込んでいたけどのでxinetdかましてたんだけど、tcpwrapperを使うmod_wrapとtcpwrapper likeなアクセス制御が出来るmod_wrap2 ってモジュールあったのでdocument読んだ。

ただ、mod_wrapは正逆引きが一致しないとアクセスを拒否るっていうlibwrapの仕様(-DPARANOID) があるようなので、tcp wrapper likeなmod_wrap2を使ってみる。

Question: Using mod_wrap, connections from hosts that have broken reverse DNS mappings are refused. OpenSSH uses the same libwrap library, and this doesn't happen. Is it a bug in mod_wrap?
Answer: No, it is not, strictly speaking, a bug in mod_wrap.

Users who encounter this issue will usually find log messages that look like the any/all of the following in their syslog:

proftpd: warning: can't verify hostname: gethostbyname(dns-name) failed
proftpd: warning: can't verify hostname: getaddrinfo(anothername.net, AF_INET) failed
proftpd: warning: host name/name mismatch: somedomain.com != vs-23.somename.com
These log messages do not, in fact, come from proftpd. Instead, they come from the libwrap library, which is used by the mod_wrap module. In particular, the libwrap library emits these log messages when it has been compiled with the -DPARANOID compile-time option (and most installations of the libwrap library are compiled this way).
OpenSSH allows such connections because the OpenSSH code, when using the libwrap library, does not check for paranoid/unknown results from the host_access() function of the libwrap library. The mod_wrap module for ProFTPD does check for these values, thus why those connections are refused by mod_wrap but not OpenSSH. This just demonstrates that not all applications use the libwrap library the same way.

mod_wrap, mod_wrap2 の場合は特定のユーザのみにtcpwrapperを適用したり、ユーザごとに~/my.allow, ~/my.deny などを用意できて柔軟な設定が可能。

mod_wrap

configureに--with-modules=mod_wrap か--with-shared=mod_wrap を追加する。sharedの場合は/etc/proftpd.conf にloadmoduleを追記。

# sharedの場合はLoadModuleを追加
LoadModule  mod_wrap.c
TCPAccessFiles /etc/hosts.allow /etc/hosts.deny

mod_wrap2

configureに--with-modules=mod_wrap2:mod_wrap2_file or --with-shared=mod_wrap2:mod_wrap2_file を追加。fileじゃなくてsql baseのmod_wrap2_sql もある。

# sharedの場合はLoadModuleを追加
LoadModule  mod_wrap2.c
LoadModule  mod_wrap2_file.c
WrapEngine on
WrapTables file:/etc/hosts.allow file:/etc/hosts.deny

mod_wrap2 はtcp wrapper "like"なのでlibwrap moduleは使っていない。

# ldd /usr/local/libexec/mod_wrap*so
/usr/local/libexec/mod_wrap.so:
linux-vdso.so.1 =>  (0x00007fffda5ff000)
libwrap.so.0 => /lib64/libwrap.so.0 (0x00007f181a302000)
libnsl.so.1 => /lib64/libnsl.so.1 (0x00007f181a0e9000)
libc.so.6 => /lib64/libc.so.6 (0x00007f1819d47000)
/lib64/ld-linux-x86-64.so.2 (0x00000031e5200000)
/usr/local/libexec/mod_wrap2.so:
linux-vdso.so.1 =>  (0x00007fff9fbff000)
libc.so.6 => /lib64/libc.so.6 (0x00007f5cb5b7b000)
/lib64/ld-linux-x86-64.so.2 (0x00000031e5200000)
/usr/local/libexec/mod_wrap2_file.so:
linux-vdso.so.1 =>  (0x00007fffdc9ff000)
libc.so.6 => /lib64/libc.so.6 (0x00007f1e477cc000)
/lib64/ld-linux-x86-64.so.2 (0x00000031e5200000)

xinetd のtcpwrapperの制御との違い

xinetd の場合はhosts.allow , hosts.deny で拒否されている場合、ftp で接続した瞬間に拒否される。

# ftp 192.168.0.1
Connected to 192.168.0.1 (192.168.0.1).
421 Service not available, remote server has closed connection
ftp>

defaultではmod_wrap, mod_wrap2 の場合はhosts.allow, hosts.deny で拒否されていても、パスワードを入力後に(パスワードがあっていても) 拒否される。

# ftp 192.168.0.1
Connected to 192.168.0.1 (192.168.0.1).
220 ProFTPD 1.3.4a Server (ProFTPD Default Installation) [192.168.0.1]
Name (192.168.0.1:hoge): hoge
331 Password required for hoge
Password:
530 Access denied
Login failed.
421 Service not available, remote server has closed connection

これを変更する場合はWrapOptionsにCheckOnConnect を設定する。ユーザ名の認証前に拒否をするので、WrapUserTablesではなくて、WrapTablesとの併用が必要。(WrapOptions は 1.3.4rc1 以降で利用可能)

WrapEngine on
WrapTables file:/etc/hosts.allow file:/etc/hosts.deny
WrapOptions CheckOnConnect

mod_wrap2 でユーザごとにアクセス制御のファイルを設定する

↑このURLのWrapUserTablesのsampleはユーザのexpressionが抜けていて間違っているので注意。

WrapUserTables * file:~/my.allow file:~/my.deny

ユーザのホームディレクトリを700 にしているとmy.allow, my.deny が読めなくてaclが効かない(すべて許可する)ようになるのでこれも注意。