スパムフィルタの適用実績を調べる

Postfix の main.cf で

smtpd_client_restrictions =
    reject_rbl_client bl.spamcop.net,
    # 中略…
    permit

のように複数のブラックリストデータベース(MAPS RBL)を設定していて、実際どれが使われているのか判断したい場合、以下のようにして実際に何件のメールについてブロックが適用されたか調べられます。
 

$ cat /var/log/maillog | perl -ne ‘if(/blocked using (.+?);/){print $1.”\n”;}’ | sort | uniq -c

結果例:

$ cat /var/log/maillog | perl -ne ‘if(/blocked using (.+?);/){print $1.”\n”;}’ | sort | uniq -c
  45 bl.spamcop.net
   4 list.dsbl.org
   7 sbl-xbl.spamhaus.org

パーティション暗号化(gbde, geli)

 
http://hsdiary.blogspot.com/2007/03/comparison-of-gbde-and-geli.html
 
FreeBSD では FreeBSD 5 から使える gbde (GEOM bde)と、FreeBSD 6 から追加された geli (GEOM eli) の二つの暗号化されたファイルシステムが提供されていますが、geli のほうが圧倒的にパフォーマンスが上らしい。
 
geli を利用できるようにするには、/boot/loader.conf に以下の行を追加するのが簡単です。

geom_eli_load=”YES” # gbde の場合は geom_bde_load=”YES”

一時的なものでいいのであればもちろん

root# kldload geom_eli

でロードできます。
 
参考:
geli(8)
mdconfig の使い方色々
GEOM_ELI を PGPDisk や TrueCrypt のように使う方法。

jail が起動できない

rc.conf に設定を追加して /etc/rc.d/jail restart したところ

jail: getpwnam: root: No such file or directory

と出て起動できなかった。
 
/etc/passwd などアカウント関係のファイルが欠落しているのが原因。
 

# cp /etc/master.passwd /etc/group /path/to/jail/etc/

と、まずどこかから設定をコピーをして必要なアカウントだけ取捨選択した上で

pwd_mkdb -p -d /path/to/jail/etc /path/to/jail/etc/master.passwd

を実行して jail の /etc/passwd を作成してやれば解決です。

pf でルーティング

FreeBSD で pf を使ってルータを作るメモ。
 
目的:
ネットワークインターフェイスが二つあり、それぞれのインターフェイスに外部ネットワーク、内部ネットワークとして割り当てるとする。
内部→外部の通信は IP マスカレード(NAPT)で透過的に通信できるようにし、外部→内部の通信は特定のポートのみ NAT でサーバにマッピングする。
 
適用例:
A. FreeBSD をルータとして動作させる。
B. (応用) jail を仮想プライベートネットワークに入れ、外への通信を制御する。
 


設定方法(A):
…外部ネットワークインターフェイスを fxp0, 内部ネットワークインターフェイスを fxp1 としてルータとして設定する場合
/etc/rc.conf:

defaultrouter=”192.168.1.1″ # 外部のデフォルトゲートウェイ
 
# 外部インターフェイス
ifconfig_fxp0=”inet 192.168.1.2 192.168.1.255 netmask 255.255.255.0″
# 内部インターフェイス
ifconfig_fxp1=”inet 10.0.0.1 10.0.0.255 netmask 255.255.255.0″
 
# pf を有効化
pf_enable=YES
pf_rules=”/etc/pf.conf”
pf_flags=””
pflog_enable=”YES”
pflog_logfile=”/var/log/pflog”
pflog_flags=””

/etc/pf.conf:

# 外部ネットワークインターフェイス
ext_if=”fxp0″
# 内部ネットワークインターフェイス
int_if=”fxp1″
####
 
table <private> const { 10.0.0/24 }
 
# IP マスカレード
nat on $ext_if inet from ($int_if) to ! <private> -> ($ext_if)
 
# NAT 設定。外からの http(80), https(443) は内部の 10.0.0.5 に、smtp(25) は内部の 10.0.0.6 に割り当て
rdr pass on $ext_if proto tcp from any to ($ext_if) port {80, 443} -> 10.0.0.5
rdr pass on $ext_if proto tcp from any to ($ext_if) port 25 -> 10.0.0.6
 
# パケットフィルタ: 説明を簡単にするため全許可に。
pass in quick all
pass out quick all

 


設定方法(B):
…外部ネットワークインターフェイスを fxp0, 内部ネットワークインターフェイスを lo1 (ループバック) として jail を内部ネットワークインターフェイスで管理する場合。
/etc/rc.conf:

defaultrouter=”192.168.1.1″ # 外部のデフォルトゲートウェイ
 
# 外部インターフェイス
ifconfig_fxp0=”inet 192.168.1.2 192.168.1.255 netmask 255.255.255.0″
# 内部インターフェイス
ifconfig_lo1=”inet 10.0.0.1 10.0.0.255 netmask 255.255.255.0″
ifconfig_lo1_alias=”inet 10.0.0.2″
ifconfig_lo1_alias=”inet 10.0.0.3″
ifconfig_lo1_alias=”inet 10.0.0.4″
ifconfig_lo1_alias=”inet 10.0.0.5″
ifconfig_lo1_alias=”inet 10.0.0.6″
# : 以下略
 
# pf を有効化
pf_enable=YES
pf_rules=”/etc/pf.conf”
pf_flags=””
pflog_enable=”YES”
pflog_logfile=”/var/log/pflog”
pflog_flags=””
 
####
### Jail の設定 ###
jail_enable=”YES”
jail_list=”j1 j2 j3″ # 立ち上げる jail の名前のリスト
jail_set_hostname_allow=”NO”
jail_sysvipc_allow=”YES”
## jail_list で設定した jail インスタンスそれぞれについて設定 ##
# j1:
jail_j1_rootdir=”/var/jail/j1″
jail_j1_hostname=”jail_1″
jail_j1_ip=”10.0.0.2″
jail_j1_exec_start=”/bin/sh /etc/rc”
jail_j1_exec_stop=”/bin/sh /bin/rc.shutdown”
jail_j1_devfs_enable=”YES”
jail_j1_fdescfs_enable=”NO”
jail_j1_procfs_enable=”YES”
jail_j1_mount_enable=”NO”
# j2, j3 も同様に。

/etc/pf.conf:

# 外部ネットワークインターフェイス
ext_if=”fxp0″
# 内部ネットワークインターフェイス
int_if=”lo1″
####
# 以下 設定方法 A とまったく同じ
table <private> const { 10.0.0/24 }
 
# IP マスカレード
nat on $ext_if inet from ($int_if) to ! <private> -> ($ext_if)
 
# NAT 設定。外からの http(80), https(443) は内部の 10.0.0.5 に、smtp(25) は内部の 10.0.0.6 に割り当て
rdr pass on $ext_if proto tcp from any to ($ext_if) port {80, 443} -> 10.0.0.5
rdr pass on $ext_if proto tcp from any to ($ext_if) port 25 -> 10.0.0.6
 
# パケットフィルタ: 説明を簡単にするため全許可に。
pass in quick all
pass out quick all

 


参考:
FreeBSDでPacketFilter(pf)を使う

フリーで使えるフォント集

【英字フォント】
1001 Free Fonts
 
細かい利用条件などはそれぞれのフォントによって異なるようで各フォント付属の readme.txt 参照とのことですが、ほとんどのフォントが無償で商用でも自由に使えるようです。
 
misprinted type 3.0


【日本語フォント】
8*8ドット日本語フォント「美咲フォント」
 
フォントブログフリー日本語フォント配布サイトリンク
 
漢字が使える日本語フォント 無料ダウンロード46種類

PHP の 5.2.5 が mysql 5.1.23-rc と非互換な件

先日 PHP 5.2.5 をビルドしようとしたところ

/usr/src/php-5.2.5/ext/mysqli/mysqli_api.c: In function
‘zif_mysqli_change_user’:
/usr/src/php-5.2.5/ext/mysqli/mysqli_api.c:420: error: ‘NET’ has no
member named ‘last_errno’
/usr/src/php-5.2.5/ext/mysqli/mysqli_api.c:420: error: ‘NET’ has no
member named ‘last_errno’
/usr/src/php-5.2.5/ext/mysqli/mysqli_api.c:420: error: ‘NET’ has no
member named ‘last_error’
/usr/src/php-5.2.5/ext/mysqli/mysqli_api.c: In function
‘zif_mysqli_kill’:
 
以下略

というエラーが出てコンパイルができなかった。
調べたら php bug に投稿がありました。
 
http://bugs.php.net/bug.php?id=44137
 
5.1.22-rc ならいけるのに MySQL 5.1.23-rc だとダメらしい。
そして開発チームの回答。

[18 Feb 7:41pm UTC] uw@php.net

A little more info: we are discussing this internally at MySQL. Its
possible that the change which has caused this (unintended) problem will
be reverted soon.
 
[24 Feb 1:01am UTC] jani@php.net
 
And it’s not PHP problem but Mysql problem since they broke the BC in
their libs/headers. 🙂
 
[24 Feb 1:03am UTC] jani@php.net
 
And please, in the future don’t report bugs caused by some 3rd party
library here which isn’t even released as stable yet.

曰く、
「mysql が悪い。こんな(不本意な)問題を引き起こしてくれる変更は mysql 開発側がじきに元に戻してくれるかもしれないからそれを待て。
そもそもサードパーティのライブラリに安定リリース版じゃないのを使ってるのはサポート外だから報告しないでね」
っていうことだそうで。
 
…とはいっても、FreeBSD ports の databases/mysql51-client (実体は mysql51-server) が 5.1.23-rc なのが悩ましいところです。

ssh -R の応用例

– SSH サーバ A から SSH クライアント B に逆方向に SSH 接続可能にする(双方向SSH)
この方法を使うとポートが閉じている環境にも外部からSSH接続ができるようになります。

B$ ssh -R 12345:127.0.0.1:22 A # (1) 12345 は任意のポート番号
(A にログイン)
A$ ssh 127.0.0.1:12345 # (2)
(A から B に逆にログイン)
B$ echo hello

メリット:
— (2)においてクライアント(B)のIPアドレスを知らなくてもサーバからクライアントに SSH 接続ができるようになります。
— クライアント側(B)の sshd がローカルからしか接続を受けない場合でもサーバ側(A)から接続することができます。
 
デメリット:
— クライアント側(B)にも最低限ローカルから TCP で接続できる sshd (または telnetd) が必要です。
— (2)でユーザ名がサーバ側とクライアント側で異なる場合、クライアント側のログイン可能なユーザ名を知っている必要があります。
— (2)を実行するには(1)の接続を保持し続けなければなりません。

参考:

ssh を任意のポート、プロトコルの逆 proxy にする

以前「ssh を任意のポート、プロトコルの proxy にする」という記事で ssh の -L オプションを紹介しましたが、この逆バージョンについて触れていなかったので紹介しておきます。
 
ssh -L は先の記事で紹介したとおり SSHクライアントの任意のポートへの通信をSSHサーバのネットワークの任意のホスト、任意のポートに転送できるようにするためのオプションですが、ssh -L とは逆に ssh -R を使うとSSHサーバの任意のポートへの接続をSSHクライアントのネットワークの任意のホスト:ポートに転送できるようになります。
 
使い方:

ssh -R <SSHサーバ側でLISTENするポート番号>:<SSHクライアント側ネットワークの転送先ホストIPアドレス>:<転送先ホストポート番号> <SSHサーバホスト>

 
例: クライアントA(192.168.1.2)からSSHサーバB(10.0.0.1)に接続し、SSH サーバからクライアント側ネットワークのHTTPサーバC(192.168.1.3:80) に A 経由でアクセスする

 
A$ ssh -R 7777:192.168.1.3:80 10.0.0.1
–connected to B(10.0.0.1)–
B$ netstat -an | grep LISTEN | grep 7777
tcp4 0 0 127.0.0.1.7777 *.* LISTEN
B$ telnet localhost 7777
Trying 127.0.0.1…
Connected to localhost.
Escape character is ‘^]’.
HEAD / HTTP/1.0\n
\n\n
HTTP/1.1 200 OK
Date: Fri, 14 Mar 2008 10:15:35 GMT
Server: Apache
Last-Modified: Thu, 20 Dec 2007 11:25:38 GMT
Accept-Ranges: bytes
Content-Length: 18050
Connection: close
Content-Type: text/html
 
Connection closed by foreign host.

 
なお、このオプションは -L 同様 PuTTY でも利用可能なので Windows から ssh 接続するときにも有用です。
 
参考:
ssh を任意のポート、プロトコルの proxy にする(過去記事)
ssh(1) manpage(openbsd.org)

NULL は「値がない」のではなく「値が不明」

SQL では NULL を含む演算は IS NULL, IS NOT NULL と一部の論理演算を除き常に戻り値が NULL になります。
この結果として、NULL を値に持つレコードを IS NULL 以外で抽出できなくなります。
たとえば極端な例ですが

SELECT NULL != NULL

が true にならず NULL になったりします(つまり (NULL != NULL) IS NULL が真になる)。
 
この仕様は Java や PHP などのプログラミング言語から考えると不可解なものにうつりますが、 NULL は値が存在しないのではなくまだわかっていない(unknown)だけなのだ、と考えるとスッキリします。
 
値段のカラムに null を持つ商品について考えるとき、その商品は「無料」ではなく値段がまだ「決まっていない」だけ。携帯のメールアドレスが null のユーザがいたなら、その人は携帯電話を「持っていない」という意味ではなく、その人が携帯電話を持っているか「わからない」だけです。
 
指定した部署(department_id)以外にいる社員(employee)の名前を探す下記のようなクエリを実行しても、部署が null の社員の名前は含まれません。その社員が 1 の部署に配属されるかもしれないからです。

SELECT name FROM employee WHERE department_id != 1

null 値も結果に含めたい場合は下記のようにしなければなりません。

SELECT name FROM employee WHERE department_id != 1 AND department_id IS NULL

 
0 や に包括的なからっぽ(empty)という意味を持たせたるのも伝統的でいいですが、SQL では 0, と NULL を区別して有効に使うほうがよさそうです。
 
参考:
3値論理とNULL(CodeZine)

tips – PHP をストリームエディタとして使う

php -R オプションを使うと、perl の -ne オプションと同様に入力行単位で任意のコードを実行することができます。

php -R “実行するコード”

標準入力から一行ずつ $argn に格納されます。末尾の改行文字は取り除かれるため、必要であれば改行を自分で付加します。
 
例: HTMLの特殊文字をエスケープする

cat foo.html | php -R ‘echo htmlspecialchars($argn).”\n”;’