Tuesday, December 31, 2013, 18:04 - Misc
Posted by ELIN
Webサーバを新しく下記のような設定で組み直すことにした
<VirtualHost *:80>
DocumentRoot /var/www

RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}/%{HTTP_HOST} -d
RewriteRule . %{DOCUMENT_ROOT}/%{HTTP_HOST}%{REQUEST_URI} [L]
RewriteRule . https://www.google.co.jp/search?q=%{HTTP_HOST}%{REQUEST_URI}
</VirtualHost>

要するにこれはディレクトリを掘るだけで擬似的にバーチャルホストとして運用できるようにするもので、これ自体は検索すればすぐに見つかる程度の安易な方法ではあるが、ともかくずぼらな私には好ましい方法である

しかしこれはmod_rewriteの深い闇を見る

この時点での挙動は
(2) init rewrite engine with requested uri /foo.html
(3) applying pattern '.' to uri '/foo.html'
(4) RewriteCond: input='/var/www/www.test1.com' pattern='-d' => matched
(2) rewrite '/foo.html' -> '/var/www/www.test1.com/foo.html'
(2) local path result: /var/www/www.test1.com/foo.html
(1) go-ahead with /var/www/www.test1.com/foo.html [OK]

と、何の問題もなく、期待通りの挙動をしている

しかしこの方法はhttpd.confへmod_rewriteへの設定を書けないため、特定ホストでのみ運用したいルールは.htaccessで賄う必要がある
そこで.htaccessへ下記のような設定を追加すると
RewriteEngine On
RewriteRule foo/(.*) bar/$1 [L]

(2) init rewrite engine with requested uri /foo/index.html
(3) applying pattern '.' to uri '/foo/index.html'
(4) RewriteCond: input='/var/www/www.test1.com' pattern='-d' => matched
(2) rewrite '/foo/index.html' -> '/var/www/www.test1.com/foo/index.html'
(2) local path result: /var/www/www.test1.com/foo/index.html
(1) go-ahead with /var/www/www.test1.com/foo/index.html [OK]
(3) [perdir /var/www/www.test1.com/] strip per-dir prefix: /var/www/www.test1.com/foo/index.html -> foo/index.html
(3) [perdir /var/www/www.test1.com/] applying pattern 'foo/(.*)' to uri 'foo/index.html'
(2) [perdir /var/www/www.test1.com/] rewrite 'foo/index.html' -> 'bar/index.html'
(3) [perdir /var/www/www.test1.com/] add per-dir prefix: bar/index.html -> /var/www/www.test1.com/bar/index.html
(2) [perdir /var/www/www.test1.com/] strip document_root prefix: /var/www/www.test1.com/bar/index.html -> /www.test1.com/bar/index.html
(1) [perdir /var/www/www.test1.com/] internal redirect with /www.test1.com/bar/index.html [INTERNAL REDIRECT]
(2) init rewrite engine with requested uri /www.test1.com/bar/index.html
(3) applying pattern '.' to uri '/www.test1.com/bar/index.html'
(4) RewriteCond: input='/var/www/www.test1.com' pattern='-d' => matched
(2) rewrite '/www.test1.com/bar/index.html' -> '/var/www/www.test1.com/www.test1.com/bar/index.html'
(2) local path result: /var/www/www.test1.com/www.test1.com/bar/index.html
(1) go-ahead with /var/www/www.test1.com/www.test1.com/bar/index.html [OK]
(3) [perdir /var/www/www.test1.com/] add path info postfix: /var/www/www.test1.com/www.test1.com -> /var/www/www.test1.com/www.test1.com/bar/index.html
(3) [perdir /var/www/www.test1.com/] strip per-dir prefix: /var/www/www.test1.com/www.test1.com/bar/index.html -> www.test1.com/bar/index.html
(3) [perdir /var/www/www.test1.com/] applying pattern 'foo/(.*)' to uri 'www.test1.com/bar/index.html'
(1) [perdir /var/www/www.test1.com/] pass through /var/www/www.test1.com/www.test1.com

となり、結果404が返されることになる
internal redirectによって再度httpd.confのルールが評価されるために、この問題は発生する

またこのinternal redirectによる問題は似たような別の問題も引き起こす
(2) init rewrite engine with requested uri /foo/!"#$%&'().txt
(3) applying pattern '.' to uri '/foo/!"#$%&'().txt'
(4) RewriteCond: input='/var/www/www.test1.com' pattern='-d' => matched
(2) rewrite '/foo/!"#$%&'().txt' -> '/var/www/www.test1.com/foo/!"#$%&'().txt'
(2) local path result: /var/www/www.test1.com/foo/!"#$%&'().txt
(1) go-ahead with /var/www/www.test1.com/foo/!"#$%&'().txt [OK]
(3) [perdir /var/www/www.test1.com/] strip per-dir prefix: /var/www/www.test1.com/foo/!"#$%&'().txt -> foo/!"#$%&'().txt
(3) [perdir /var/www/www.test1.com/] applying pattern 'foo/(.*)' to uri 'foo/!"#$%&'().txt'
(2) [perdir /var/www/www.test1.com/] rewrite 'foo/!"#$%&'().txt' -> 'bar/!"#$%&'().txt'
(3) [perdir /var/www/www.test1.com/] add per-dir prefix: bar/!"#$%&'().txt -> /var/www/www.test1.com/bar/!"#$%&'().txt
(2) [perdir /var/www/www.test1.com/] strip document_root prefix: /var/www/www.test1.com/bar/!"#$%&'().txt -> /www.test1.com/bar/!"#$%&'().txt
(1) [perdir /var/www/www.test1.com/] internal redirect with /www.test1.com/bar/!"#$%&'().txt [INTERNAL REDIRECT]
(2) init rewrite engine with requested uri /www.test1.com/bar/!"
(3) applying pattern '.' to uri '/www.test1.com/bar/!"'
(4) RewriteCond: input='/var/www/www.test1.com' pattern='-d' => matched
(2) rewrite '/www.test1.com/bar/!"' -> '/var/www/www.test1.com/www.test1.com/bar/!"'
(2) local path result: /var/www/www.test1.com/www.test1.com/bar/!"
(1) go-ahead with /var/www/www.test1.com/www.test1.com/bar/!" [OK]
(3) [perdir /var/www/www.test1.com/] add path info postfix: /var/www/www.test1.com/www.test1.com -> /var/www/www.test1.com/www.test1.com/bar/!"
(3) [perdir /var/www/www.test1.com/] strip per-dir prefix: /var/www/www.test1.com/www.test1.com/bar/!" -> www.test1.com/bar/!"
(3) [perdir /var/www/www.test1.com/] applying pattern 'foo/(.*)' to uri 'www.test1.com/bar/!"'
(1) [perdir /var/www/www.test1.com/] pass through /var/www/www.test1.com/www.test1.com

特定の記号を含むファイル名へのリクエストはアンエスケープされ記号へ戻るが、internal redirectの際に再度エスケープされないまま渡されるため、0x23(#)以降は不要と判断され、完全に抜け落ちている

この問題を解決するために.htaccessへ
RewriteRule ^(.*)#(.*)$ $1\%23$2 [N]
と、邪悪で安易な方法だがともかく、追記してやりたいところだがこれは非常にマズい
internal redirectの際に抜け落ちこそしなくなるものの、再度このルールが評価されるため、ループしてしまうことになる

そしてこれと同等の現象だが、このような設定をすると
RewriteRule ^((?!foo/).*) foo/$1 [L]
(2) init rewrite engine with requested uri /index.html
(3) applying pattern '.' to uri '/index.html'
(4) RewriteCond: input='/var/www/www.test1.com' pattern='-d' => matched
(2) rewrite '/index.html' -> '/var/www/www.test1.com/index.html'
(2) local path result: /var/www/www.test1.com/index.html
(1) go-ahead with /var/www/www.test1.com/index.html [OK]
(3) [perdir /var/www/www.test1.com/] strip per-dir prefix: /var/www/www.test1.com/index.html -> index.html
(3) [perdir /var/www/www.test1.com/] applying pattern '^((?!foo/).*)' to uri 'index.html'
(2) [perdir /var/www/www.test1.com/] rewrite 'index.html' -> 'foo/index.html'
(3) [perdir /var/www/www.test1.com/] add per-dir prefix: foo/index.html -> /var/www/www.test1.com/foo/index.html
(2) [perdir /var/www/www.test1.com/] strip document_root prefix: /var/www/www.test1.com/foo/index.html -> /www.test1.com/foo/index.html
(1) [perdir /var/www/www.test1.com/] internal redirect with /www.test1.com/foo/index.html [INTERNAL REDIRECT]
(2) init rewrite engine with requested uri /www.test1.com/foo/index.html
(3) applying pattern '.' to uri '/www.test1.com/foo/index.html'
(4) RewriteCond: input='/var/www/www.test1.com' pattern='-d' => matched
(2) rewrite '/www.test1.com/foo/index.html' -> '/var/www/www.test1.com/www.test1.com/foo/index.html'
(2) local path result: /var/www/www.test1.com/www.test1.com/foo/index.html
(1) go-ahead with /var/www/www.test1.com/www.test1.com/foo/index.html [OK]
(3) [perdir /var/www/www.test1.com/] add path info postfix: /var/www/www.test1.com/www.test1.com -> /var/www/www.test1.com/www.test1.com/foo/index.html
(3) [perdir /var/www/www.test1.com/] strip per-dir prefix: /var/www/www.test1.com/www.test1.com/foo/index.html -> www.test1.com/foo/index.html
(3) [perdir /var/www/www.test1.com/] applying pattern '^((?!foo/).*)' to uri 'www.test1.com/foo/index.html'
(2) [perdir /var/www/www.test1.com/] rewrite 'www.test1.com/foo/index.html' -> 'foo/www.test1.com/foo/index.html'
(3) [perdir /var/www/www.test1.com/] add per-dir prefix: foo/www.test1.com/foo/index.html -> /var/www/www.test1.com/foo/www.test1.com/foo/index.html
(2) [perdir /var/www/www.test1.com/] strip document_root prefix: /var/www/www.test1.com/foo/www.test1.com/foo/index.html -> /www.test1.com/foo/www.test1.com/foo/index.html
(1) [perdir /var/www/www.test1.com/] internal redirect with /www.test1.com/foo/www.test1.com/foo/index.html [INTERNAL REDIRECT]
(2) init rewrite engine with requested uri /www.test1.com/foo/www.test1.com/foo/index.html
(3) applying pattern '.' to uri '/www.test1.com/foo/www.test1.com/foo/index.html'
(4) RewriteCond: input='/var/www/www.test1.com' pattern='-d' => matched
(2) rewrite '/www.test1.com/foo/www.test1.com/foo/index.html' -> '/var/www/www.test1.com/www.test1.com/foo/www.test1.com/foo/index.html'
(2) local path result: /var/www/www.test1.com/www.test1.com/foo/www.test1.com/foo/index.html
...

と、同様の理由から意図しないループが発生する

さて、これらの現象が発生する悪の根源はinternal redirectにあるが、仕様上どうしてもこれを回避することはできない
従って当然internal redirectを発生させるべきではなく、間違っても.htaccess(やDirectoryディレクティブ内)でmod_rewriteを走らせないのが最善策ということで落ち着くだろう

ただよく調べてみるとこの問題を回避する方法がないわけではないらしいので、もうちょっと粘ることにした

まず書いてあるようにREDIRECT_STATUSを見ればいいらしいので
<VirtualHost *:80>
DocumentRoot /var/www

RewriteEngine On
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule . - [S=100]
RewriteCond %{DOCUMENT_ROOT}/%{HTTP_HOST} -d
RewriteRule . %{DOCUMENT_ROOT}/%{HTTP_HOST}%{REQUEST_URI} [L]
RewriteRule . https://www.google.co.jp/search?q=%{HTTP_HOST}%{REQUEST_URI}
</VirtualHost>

と、した上で.htaccessは
RewriteEngine On
RewriteRule ^((?!foo/).*) foo/$1 [L]

と、する

このときの動作は
(2) init rewrite engine with requested uri /foo.html
(3) applying pattern '.' to uri '/foo.html'
(4) RewriteCond: input='' pattern='200' => not-matched
(3) applying pattern '.' to uri '/foo.html'
(4) RewriteCond: input='/var/www/www.test1.com' pattern='-d' => matched
(2) rewrite '/foo.html' -> '/var/www/www.test1.com/foo.html'
(2) local path result: /var/www/www.test1.com/foo.html
(1) go-ahead with /var/www/www.test1.com/foo.html [OK]
(3) [perdir /var/www/www.test1.com/] strip per-dir prefix: /var/www/www.test1.com/foo.html -> foo.html
(3) [perdir /var/www/www.test1.com/] applying pattern '^((?!foo/).*)' to uri 'foo.html'
(2) [perdir /var/www/www.test1.com/] rewrite 'foo.html' -> 'foo/foo.html'
(3) [perdir /var/www/www.test1.com/] add per-dir prefix: foo/foo.html -> /var/www/www.test1.com/foo/foo.html
(2) [perdir /var/www/www.test1.com/] strip document_root prefix: /var/www/www.test1.com/foo/foo.html -> /www.test1.com/foo/foo.html
(1) [perdir /var/www/www.test1.com/] internal redirect with /www.test1.com/foo/foo.html [INTERNAL REDIRECT]
(2) init rewrite engine with requested uri /www.test1.com/foo/foo.html
(3) applying pattern '.' to uri '/www.test1.com/foo/foo.html'
(4) RewriteCond: input='200' pattern='200' => matched
(1) pass through /www.test1.com/foo/foo.html
(3) [perdir /var/www/www.test1.com/] strip per-dir prefix: /var/www/www.test1.com/foo/foo.html -> foo/foo.html
(3) [perdir /var/www/www.test1.com/] applying pattern '^((?!foo/).*)' to uri 'foo/foo.html'
(1) [perdir /var/www/www.test1.com/] pass through /var/www/www.test1.com/foo/foo.html

このような結果となり、意図した挙動を示す
internal-redirectは発生してはいるものの、問題は回避されている

0x23(#)以降が抜け落ちる問題は以前解決していないものの、.htaccessにも
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule . - [S=100]
RewriteRule ^(.*)#(.*)$ $1\%23$2 [N]

と、加えることでループを回避しつつ問題を解決できる
ただこれは0x23(#)の話でしかない

と、いうのは
(2) init rewrite engine with requested uri /!"#$%&'().txt
(3) applying pattern '.' to uri '/!"#$%&'().txt'
(4) RewriteCond: input='' pattern='200' => not-matched
(3) applying pattern '.' to uri '/!"#$%&'().txt'
(4) RewriteCond: input='/var/www/www.test1.com' pattern='-d' => matched
(2) rewrite '/!"#$%&'().txt' -> '/var/www/www.test1.com/!"#$%&'().txt'
(2) local path result: /var/www/www.test1.com/!"#$%&'().txt
(1) go-ahead with /var/www/www.test1.com/!"#$%&'().txt [OK]
(3) [perdir /var/www/www.test1.com/] strip per-dir prefix: /var/www/www.test1.com/!"#$%&'().txt -> !"#$%&'().txt
(3) [perdir /var/www/www.test1.com/] applying pattern '.' to uri '!"#$%&'().txt'
(4) [perdir /var/www/www.test1.com/] RewriteCond: input='' pattern='200' => not-matched
(3) [perdir /var/www/www.test1.com/] strip per-dir prefix: /var/www/www.test1.com/!"#$%&'().txt -> !"#$%&'().txt
(3) [perdir /var/www/www.test1.com/] applying pattern '^(.*)#(.*)$' to uri '!"#$%&'().txt'
(2) [perdir /var/www/www.test1.com/] rewrite '!"#$%&'().txt' -> '!"%23$%&'().txt'
(3) [perdir /var/www/www.test1.com/] add per-dir prefix: !"%23$%&'().txt -> /var/www/www.test1.com/!"%23$%&'().txt
(3) [perdir /var/www/www.test1.com/] strip per-dir prefix: /var/www/www.test1.com/!"%23$%&'().txt -> !"%23$%&'().txt
(3) [perdir /var/www/www.test1.com/] applying pattern '.' to uri '!"%23$%&'().txt'
(4) [perdir /var/www/www.test1.com/] RewriteCond: input='' pattern='200' => not-matched
(3) [perdir /var/www/www.test1.com/] strip per-dir prefix: /var/www/www.test1.com/!"%23$%&'().txt -> !"%23$%&'().txt
(3) [perdir /var/www/www.test1.com/] applying pattern '^(.*)#(.*)$' to uri '!"%23$%&'().txt'
(3) [perdir /var/www/www.test1.com/] strip per-dir prefix: /var/www/www.test1.com/!"%23$%&'().txt -> !"%23$%&'().txt
(3) [perdir /var/www/www.test1.com/] applying pattern '^((?!foo/).*)' to uri '!"%23$%&'().txt'
(2) [perdir /var/www/www.test1.com/] rewrite '!"%23$%&'().txt' -> 'foo/!"%23$%&'().txt'
(3) [perdir /var/www/www.test1.com/] add per-dir prefix: foo/!"%23$%&'().txt -> /var/www/www.test1.com/foo/!"%23$%&'().txt
(2) [perdir /var/www/www.test1.com/] strip document_root prefix: /var/www/www.test1.com/foo/!"%23$%&'().txt -> /www.test1.com/foo/!"%23$%&'().txt
(1) [perdir /var/www/www.test1.com/] internal redirect with /www.test1.com/foo/!"%23$%&'().txt [INTERNAL REDIRECT]

で、400が返されログの出力はここで止まる
これは今まで抜け落ちていた0x25(%)が起因となるもので、0x26(&)が続く0x25(%)が不正と判断されて発生している

この問題はhttpd.confへ
RewriteMap escape int:escape
と、した上で.htaccessへ
RewriteRule ^(.*)$ ${escape:$1}
と、することで回避できる

余談だがこの内容を書くにあたって2日要しており、ここまでは昨日の話

実は記号問題は重要視していなかった
これは真面目に調べていなかったということと同意義で、実はこんな面倒なことは必要ない
と、いうのも前述したとおり、そもそも.htaccessでmod_rewrite使うべきではない、ということで結論が出てしまっていた(し、それで運用することにした)からだ

ところが調べてみるとBフラグというものが存在していて、これは
RewriteRule ^(.*)$ $1 [B]
と、するだけでよく
(2) init rewrite engine with requested uri /!"#$%&'().txt
(3) applying pattern '.' to uri '/!"#$%&'().txt'
(4) RewriteCond: input='' pattern='200' => not-matched
(3) applying pattern '.' to uri '/!"#$%&'().txt'
(4) RewriteCond: input='/var/www/www.test1.com' pattern='-d' => matched
(2) rewrite '/!"#$%&'().txt' -> '/var/www/www.test1.com/!"#$%&'().txt'
(2) local path result: /var/www/www.test1.com/!"#$%&'().txt
(1) go-ahead with /var/www/www.test1.com/!"#$%&'().txt [OK]
(3) [perdir /var/www/www.test1.com/] strip per-dir prefix: /var/www/www.test1.com/!"#$%&'().txt -> !"#$%&'().txt
(3) [perdir /var/www/www.test1.com/] applying pattern '.' to uri '!"#$%&'().txt'
(4) [perdir /var/www/www.test1.com/] RewriteCond: input='' pattern='200' => not-matched
(3) [perdir /var/www/www.test1.com/] strip per-dir prefix: /var/www/www.test1.com/!"#$%&'().txt -> !"#$%&'().txt
(3) [perdir /var/www/www.test1.com/] applying pattern '^(.*)$' to uri '!"#$%&'().txt'
(5) [perdir /var/www/www.test1.com/] escaping backreference '!"#$%&'().txt' to '%21%22%23%24%25%26%27%28%29%2etxt'
(2) [perdir /var/www/www.test1.com/] rewrite '!"#$%&'().txt' -> '%21%22%23%24%25%26%27%28%29%2etxt'
(3) [perdir /var/www/www.test1.com/] add per-dir prefix: %21%22%23%24%25%26%27%28%29%2etxt -> /var/www/www.test1.com/%21%22%23%24%25%26%27%28%29%2etxt
(3) [perdir /var/www/www.test1.com/] strip per-dir prefix: /var/www/www.test1.com/%21%22%23%24%25%26%27%28%29%2etxt -> %21%22%23%24%25%26%27%28%29%2etxt
(3) [perdir /var/www/www.test1.com/] applying pattern '^((?!foo/).*)' to uri '%21%22%23%24%25%26%27%28%29%2etxt'
(2) [perdir /var/www/www.test1.com/] rewrite '%21%22%23%24%25%26%27%28%29%2etxt' -> 'foo/%21%22%23%24%25%26%27%28%29%2etxt'
(3) [perdir /var/www/www.test1.com/] add per-dir prefix: foo/%21%22%23%24%25%26%27%28%29%2etxt -> /var/www/www.test1.com/foo/%21%22%23%24%25%26%27%28%29%2etxt
(2) [perdir /var/www/www.test1.com/] strip document_root prefix: /var/www/www.test1.com/foo/%21%22%23%24%25%26%27%28%29%2etxt -> /www.test1.com/foo/%21%22%23%24%25%26%27%28%29%2etxt
(1) [perdir /var/www/www.test1.com/] internal redirect with /www.test1.com/foo/%21%22%23%24%25%26%27%28%29%2etxt [INTERNAL REDIRECT]
(2) init rewrite engine with requested uri /www.test1.com/foo/!"#$%&'().txt
(3) applying pattern '.' to uri '/www.test1.com/foo/!"#$%&'().txt'
(4) RewriteCond: input='200' pattern='200' => matched
(1) pass through /www.test1.com/foo/!"#$%&'().txt
(3) [perdir /var/www/www.test1.com/] strip per-dir prefix: /var/www/www.test1.com/foo/!"#$%&'().txt -> foo/!"#$%&'().txt
(3) [perdir /var/www/www.test1.com/] applying pattern '.' to uri 'foo/!"#$%&'().txt'
(4) [perdir /var/www/www.test1.com/] RewriteCond: input='200' pattern='200' => matched
(1) [perdir /var/www/www.test1.com/] pass through /var/www/www.test1.com/foo/!"#$%&'().txt

このように問題を回避できる

さて、この内容を書くための検証環境は最終的に
RewriteEngine On
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule . - [S=100]
RewriteCond %{DOCUMENT_ROOT}/%{HTTP_HOST} -d
RewriteRule . %{DOCUMENT_ROOT}/%{HTTP_HOST}%{REQUEST_URI} [L]
RewriteRule . https://www.google.co.jp/search?q=%{HTTP_HOST}%{REQUEST_URI}


RewriteEngine On
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule . - [S=100]
RewriteRule ^(.*)$ $1 [B]
RewriteRule ^((?!foo/).*) foo/$1 [L]

このような設定で動作している

運用上障害になり得る問題は解決しているが、実は1つ踏んだままの地雷がある
それはmod_autoindexを使った場合で、/へのリクエストを/www.test1.com/foo/だと勘違いしてしまう
確かにmod_rewriteによって/へのリクエストは/www.test1.com/foo/になるのだが、mod_autoindexで生成されたページでIndex of /www.test1.com/fooと表示されることを期待はしていないし、Parent Directoryのリンクが見えて、そのリンク先が/www.test1.com/になるのは困る

これは解決できていない
しいて言えば前述しているように.htaccessでmod_rewriteを使わなければ再現しない
add comment ( 3425 views )
Thursday, November 14, 2013, 12:36 - OS / Unix, *BSD, Solaris, Misc
Posted by ELIN
随分前の雑談の中で出た話なのだが、RS-232Cのクロスケーブルがなくてこれは中途半端にしか検証されていなかったが、物が手に入ったので結論が出た
もっとも予測はされていたのだが

一応世界で見れば最低でも1人は同じことをして遊ぼうとしている人がいるらしく、公式フォーラムで起動しないと言っているのを見付けることができる
それに対する回答としては普通にCDからインストールする(つまりNanoBSDを使わない)とか、HP t5720 PCI Expansion Moduleを買えとのことだが、これによって問題が解決するか否かは不明のままだ

雑談の続きは「動かないわけがない」ということなので結果試すことになった

そもそも上記問題は起動しないのではなく、起動はしているが、VGAへ出力されないため不明ということになる
雑談の中の予測は起動はしている、しかしVGAへ出力されないということを知らない

これは恐らくNanoBSDではないpfSenseを使うことで解決する
例えばUSB-FlashにCDからインストールしてそれを挿せば何の問題もない

さて、結論から言えば……
というか過程における問題は何もなかったので書くことがないが、ともかく

普通に直接フラッシュへイメージを書き込む
具体的なファイル名はpfSense-2.1-RELEASE-512mb-i386-nanobsd.img.gzになる

pfSenseを書き込んだ後、何の問題もなくブートローダが走る
前述の通り、NanoBSDを使っているイメージなのでここで出力が止まる
そしてコンソールへ出力が見える

1つ問題があるとするならばACPI関連で
ACPI Error: [RBYT] Namespace lookup failure, AE_NOT_FOUND (20101013/psargs-464)
ACPI Error: Method parse/execution failed [\RTMP] (Node 0xc3a21dc0), AE_NOT_FOUND (20101013/psparse-633)
ACPI Error: Method parse/execution failed [\_TZ_.THRM._TMP] (Node 0xc3a21c20), AE_NOT_FOUND (20101013/psparse-633)

のようなエラーが頻繁に出力される
これは素直にACPIを無効にすればよい (参考:https://doc.pfsense.org/index.php/Disable_ACPI)

ちなみに今現在はNanoBSDでもVGA版が存在しているので出力がどうこうの問題は発生しない
またVGA版で起動することも確認している
add comment ( 3219 views )
Tuesday, November 5, 2013, 17:32 - Misc
Posted by ELIN
以前からメインマシンのスペックにいい加減限界を感じていたこともあり、DVI4出力のグラフィックカードが壊れたことを機に新調するということになったのだが……

・旧
AMD Phenom X4 9950 BE
DFI LP UT 790FX-M2R
UMAX Pulsar DCDDR2-4GB-800 (x2)
SAPPHIRE HD 6950 2GB GDDR5 D3E
GECUBE GC-D26XT2-F5
Intel PRO/1000 PT Desktop Adapter

・新
Intel Core i5 4670
MSI Z87-G45 GAMING
Corsair CMX16GX3M2A1600C11
SAPPHIRE HD 6950 2GB GDDR5 D3E
SAPPHIRE HD6450 1G DDR3 PCI-E HDMI/DVI-D/VGA (x2)
Intel PRO/1000 PT Desktop Adapter (x2)

AMD信者の私も今回は流石にIntel製
と、いうのもAMDはCP比ですらIntelに勝てていないのでもうAMDを選ぶ理由が何もない
時代は完全にIntel

またDVI4出力という特殊なグラフィックカードは安価で互換が効くものへ置き換える
その絡みでPCIex16が8-4-4で動作するマザーボードを選択
HaswellではなくIvyだと選択肢が広がるのだが、なぜかHaswellの場合は8-4-4がMSIかASRock(かIntel純正、高い)しかない

記載していないがメインマシンのシステム用HDDはML115 G1に付属していた80GBのHDDを使用していたが、容量不足感が否めなかった
よって丁度未開封で余っている1TBのHDDへddして換装

さて、そもそもこの時点で動くのかという気がしてくる
CPUだけ見てもPhenom X4 9950 BE(2008年7月)からi5 4670(2013年6月)と世代差もあるが、そもそもベンダーが違うので嫌な予感はしていた
と、いうか移行前と移行後の共通点はグラフィックカード1枚とネットワークカード1枚しかない

実際組んでみると案の定0x0000007bで青くなる
このエラーは主にSATA IDE互換でインストールしたシステムをSATA AHCIで繋ぎ直して起動しようとすると簡単に再現できる
だが今回はIDE互換でも状況変わらず

そもそも移行前と移行後のH/W構成が大きく異なっているし、システムのHDDも違う
ブート方法もMBRからUEFIになっていたりと、何が原因なのか全くわからない
そして1つ1つ検証する気力もない

しかし結論から言えばわからないなりに復旧まで漕ぎ着けた

まず移行前の環境はMBRなので、確実にMBRでブートするようBIOSを設定する
HDDだけでなくCD/DVDもUEFIを使用しない

次にSATA IDE互換かSATA AHCIかを設定する
本来であれば以前の環境と合わせるのが正しいが、後述する方法でこれは結果に影響しないので、AHCIにしておく

そしてWindows 7のディスクを使ってコマンドプロンプトを立ち上げる

次にHDDを移行したためか、ドライブレターがおかしくなっているのでdiskpartを使ってこれを修正する
Windows 7はシステムドライブに100MBの領域を確保するが、これがCになっており、CであるはずのパーティションがEだったので
DISKPART> list volume

DISKPART> list volume

Volume ### Ltr Label Fs Type Size Status Info
---------- --- ----------- ----- ---------- ------- --------- --------
Volume 0 F GSP1RMCULXF UDF DVD-ROM 3168 MB Healthy
Volume 1 C ????????? NTFS Partition 100 MB Healthy System
Volume 2 E NTFS Partition 931 GB Healthy Boot
Volume 3 D D_DEVEL NTFS Partition 931 GB Healthy

DISKPART> select volume 1
DISKPART> remove letter=C
DISKPART> select volume 2
DISKPART> assign letter=C

と、する
しかしこれは未検証故に正しい手順であるかどうかはわからない
OSが正常に起動しているとするならば正しくないのは明確だが、レスキューモードではこのドライブレターであることが正しいかもしれないということ

変更が済んだら
> bootsect /nt60 C:
としてMBRを更新する

最後にレジストリを変更する (参考:http://mo.kerosoft.com/0175/)
cd /d C:\Windows\System32\config
reg load HKLM\tempsys system

と、した後にレジストリエディタを起動し
・HKLM\tempsys\ControlSet001\services\Msahci
・HKLM\tempsys\ControlSet002\services\Msahci
・HKLM\tempsys\ControlSet001\services\IastorV
・HKLM\tempsys\ControlSet002\services\IastorV
のStartの値を3から0に変更する

参考先を読むとIDE互換からAHCIへの移行の話としてこの手順が出てくるが、実際どうもこれはレジストリの変更によって全てのデバイスが再インストールされる有用な手段であるらしい
何らかの移行作業を行うときは事前にこの手順を行うことで問題を回避できるかもしれない

実際の復旧には記述していないこともやったが、恐らく復旧に関わるであろうものは記述した手順だろうと思う
1 comment ( 23235 views )
Friday, October 18, 2013, 19:40 - Misc
Posted by ELIN
1秒以内にレスポンスを返せないザコってるサーバのせいでWebページの表示が遅いときがある
大概アクセス解析のクソやSNSのクソどうでもいいねボタンだったりするわけだが、ともかく、AdBlockなどがあればいいが、実際インストールされているのはメインマシンのメインブラウザのみだったりする
そもそも自由度もない非力な携帯端末にこれは無理があるし、大量にあるVM上のシステム全てにインストールしていくのもなんだか

なのでDNSが返すIPを書き換えてFWでそのIPに対するアクセスをブロックするという方法で解決を試みる

しかしpfSenseのDNS forwarderの項目、Host Overridesでは単一のホストしか指定できないため、サブドメインを大量に使っている忍者ツールズとかいうゴミをブロックするには1つ1つ書かなければならなくなる
Domain Overridesは一見動きそうだが、これは違う
指定したドメインの場合、任意のDNSサーバへ聞きに行くという設定項目で今回の要件は満たせない

pfSenseのDNS forwarderはDnsmasqなので何かないかと調べてみると
# Add domains which you want to force to an IP address here.
# The example below send any host in doubleclick.net to a local
# webserver.
#address=/doubleclick.net/127.0.0.1

こんなことが書いてあった

幸いAdvancedの項目がdnsmasq.confの内容そのものとして設定できるので、ここに
address=/doubleclick.net/254.254.254.254
address=/google-anaytics.com/254.254.254.254
address=/shinobi.jp/254.254.254.254
address=/ak.facebook.com/254.254.254.254
address=/connect.facebook.net/254.254.254.254
address=/b.st-hatena.com/254.254.254.254
address=/platform.twitter.com/254.254.254.254

ザコってるドメインを全て254.254.254.254とする
正直このアドレスが適切かどうかはわからないが……

あとはRulesのFloatingで全てのインターフェースを選択し、Destination 254.254.254.254をRejectすれば完成
add comment ( 3274 views )
Saturday, March 2, 2013, 12:51 - OS / Linux
Posted by ELIN
先日t5720がヤフオクで12台セット10800円だったので知り合いと共同購入

内6台が届いた
(\10800+送料\5160)/12で\1330/台、お得

早速展開、まあ中身の画像はGoogleですぐ出てくるが

問題はこの角度

PCIだが「超ロープロなカードなら刺さるんじゃね」とか「ライザーカード使うんじゃね」とか話してたが、実物を見るとメモリほどの余裕しかないし、ライザーカードでなんとかする隙間すらなかった
別に使う予定はないからいいけど、仮に使うなら側板を外して運用か、穴を空けるしかない

さてDebianで運用する方法だが、flashが512MBしかないのでいくらDebianでも通常の方法では容量不足でインストールできない
最も単純な解決方法は諦めてDSLなどを使用することだが、Debianの豊富なリポジトリを使いたいのでだめ
多少古くてもいいならt5725のfirmwareを使うという手もある
但しflash向けに最適化されておらず、I/Oが直接flashへ入るので寿命が気になってくるのでだめ

色々と考えたが最終的にはrorootでaufsが噛んでいれば一応は最低要件を満たせるので、live-helperを使うことにした
幸いlive-helperがusbflash向けのddイメージを作成できるようなので、まあusbではないがddでぶちこんでしまえば起動くらいはするだろうという考え

早速作成とその検証にかかるが、この仮定であることに気付く
live-helperで作成するイメージはいわゆるスナップショット機能を含んでいる
今のlivecdなら大体この機能を持っていて、これはlivecdで起動して作業データをusbflashへ自動で保存してくれるというやつで、要するにlivecdとusbflashを持ち歩けばどこでも作業環境が呼び出せるというやつだ

この機能をうまく使えばインテリスイッチなどで見る設定変更後保存しない限り再起動すると元の状態で立ち上がってくるというような本当のfirmwareっぽい実装ってできるよね?と
だが探してみるとlive-helper自体ドキュメント不足な感じがあるし、そもそもこういうハック的な情報が出てこないので1つ1つ検証することになった

まずスナップショット機能としては4種類から選べる
・live-rw
・home-rw
・live-sn
・home-sn
でlive-*はファイルシステム全体(/以下)を対象とし、home-*は(恐らく、未検証)/home以下を対象とする
これはデバイスを跨がない、単純に言えばrsync -xと同様の動作だが、例えば/tmpがtmpfsでマウントされている場合、/tmp以下は対象とならない
また/etc/live-snapshot.exclude_listに記述されているものも対象にならない
*-rwは起動時に-o rwで該当するデバイスをマウントし、以降そのデバイスへI/Oを流す
つまり基本的に即反映される、何らかの変更はその後に電源を引っこ抜いてもファイルシステムが正常であるとするなら反映されている
*-snは起動時に前回保存された差分をramfsへ展開し、以降のI/Oもそのramfsへ反映される
このramfsのデータは正常終了時に新たな差分として該当デバイスへ書き出し、haltする
つまり電源を引っこ抜かれると途中の変更は全て消失することになる

この4種類の名称は識別子で、例えばHDDを繋いでそのHDDが/dev/sdbならば
mke2fs -L live-rw /dev/sdb1
tune2fs -L live-rw /dev/sdb1

などで識別子をボリュームラベルに設定すると起動時に認識し、そのようなデバイスとして扱う
この場合であればファイルシステムへの変更は/dev/sdb1へ即座に保存され、次回以降も特殊な操作を必要とせず、前回と同様の状態で起動する

但しこれらは完全に自動で認識してくれるわけではなく、kernelパラメータとして"persistent"を渡す必要がある
persistentを渡さない場合、どういう状態であれ無視されてデフォルトの状態で起動する
また基本的には直下(と表現すべきか……)しか探してくれないので例えばlive-snで差分データが/live/live-sn.cpio.gzのような場所(rootfsからの話ではないことに注意、詳細は後述)に保存されている場合はpersistentを渡した上で"persistent-path=/live/"(末尾/必須?)も渡す必要が出てくる
persistent-pathは通常渡す必要がないが、live-snapshotコマンドで融通を利かせたい場合に使うことになる

live-snapshotコマンドは任意のタイミング、任意の場所を任意の場所へスナップショットを保存でき、この機能の自由度を高めてくれる
使い方は単純で
live-snapshot -r /:/dev/sdb1:/live/live-sn.cpio.gz
のようにスナップショットを保存元、保存先デバイス、そのパスを":"で区切って-rで渡す
例のlive-sn.cpio.gzのlive-snの部分は識別子で、その影響を受ける
なのでこの名称は必ず4種類のいずれかでなければ読み込んでくれない

さて、話を戻して要件をまとめると
・flash saveでファイルシステムのスナップショットを保存、但し一部除く(/var/logなど)
・flash clearでスナップショットを破棄、ファクトリーデフォルトに戻る
・上記2点以外の操作でスナップショットは変更されない
と、なる

まずこのflashコマンドは
#!/bin/sh

case $1 in
save)
live-snapshot -r /:`df /live/image|awk '/^\/dev\//{print$1}'`:/live/live-sn.cpio.gz
;;
clear)
mount -o remount,rw `df /live/image|awk '/^\/dev\//{print$1}'`
rm -f /live/image/live/live-sn.cpio.gz
mount -o remount,ro `df /live/image|awk '/^\/dev\//{print$1}'`
;;
*)
;;
esac

こんなスクリプトを/sbinに置き
lb config --bootappend-live "persistent persistent-path=/live/"
と、する
スナップショットはrootfsから見ると/live/image/live/以下にlive-sn.cpio.gzとして保存され、起動時に読み込まれるようになる
flashである/dev/sda1は/live/imageにマウントされていて、その/live以下にrootfs(filesystem.squashfs)があるので、同一のディレクトリにイメージを保存したいという理由でこうしている

しかしこれは想定の動作をしない
何故ならlive-sn.cpio.gzを読み込んだ時点でこれがスナップショットの保存先であることをinitrdの中で/etc/live/boot.d/snapshot.confに出力している
これがOSの正常終了時に/etc/init.d/live-bootに読み込まれ、自動的にlive-snapshotを実行してしまうために任意ではないタイミングでスナップショットが保存されてしまう
本来はそうあるべきだろうが、今回の要件ではロールバックさせなければならないのでこの制御を削除する必要がある

方法は様々あるが、最も簡単なのは/etc/live/boot.d/snapshot.confを読ませないことで、これは
#!/bin/sh
sed -i 's/^.*\. \${SNAPSHOT_CONF}$/#&/' /etc/init.d/live-boot

なファイルをlive-helperのconfig/chroot_local-hooks/以下に置いておけば解決する

これでflashに優しいfirmware的な何かが作れるようになった

実際に使っているスクリプトはこちら

これでOS部分は完成したので次はcomサーバに取りかかる
comサーバとは何なのか、ということだがこのt5720にusb-rc232変換を挿しまくってシリアルが必須な機器をt5720へのssh経由で管理できるようにしようというもの

これはぶろぐの内容的にはオマケみたいなもので
まず
ttyS0:x:1000:20::/home/com:/bin/sh
ttyS1:x:1000:20::/home/com:/bin/sh
ttyS2:x:1000:20::/home/com:/bin/sh
ttyS3:x:1000:20::/home/com:/bin/sh
ttyUSB0:x:1000:20::/home/com:/bin/sh
ttyUSB1:x:1000:20::/home/com:/bin/sh
ttyUSB2:x:1000:20::/home/com:/bin/sh
ttyUSB3:x:1000:20::/home/com:/bin/sh

こういう感じにユーザを作る

で、/home/com/.profileを
#!/bin/sh

if [ -c /dev/$LOGNAME ];then
case $LOGNAME in
ttyS0)
bps=115200
;;
ttyUSB0)
bps=9600
;;
*)
;;
esac

screen -xRR -S $LOGNAME /dev/$LOGNAME $bps
fi

と、する

こうすることでt5720へttyUSB0でsshを張ると即座にシリアルポートが使えるようになるというわけです
add comment ( 5688 views )

<<First <Back | 1 | 2 | 3 | 4 | Next> Last>>