linuxの最近のブログ記事

squidを使ってプロクシサーバをたてた。
NATの内側にproxyがある。

http/httpsは問題ないが、LAN内のブラウザ→squid→ftpリソース、だと取得できない。
試しにsquidが動作しているサーバでwgetを使って同じftpリソースを取得してみたがこっちはOK。なので、ネットワーク的にはいけるはず。

PASVになってないのかな?と思ってtsharkでキャプチャしてみると、PASVに対して肯定応答をもらっているのに、その後なぜかPORTを送り、相手のサーバからConnection確立できない、という応答。

今度はstraceで様子を見てみると、PASVを送ったあと相手のサーバに接続しようとしたところでconnectがEACCESでエラーになっている。

どういうこと?と思ったけど「squid ftp selinux」で検索してみると良くある話題のようだ。
selinuxポリシー内で、squidがftp接続に行けるポートを制限しているらしい。

selinuxってこういう制限もするのか。

実のところ、selinuxでブロックされている、ということは後からわかった。
試行錯誤しまくった過程で、iptablesのモジュール(/etc/sysconfig/iptables-configのIPTABLES_MODULES)にip_conntrack_ftp を加えても通るようになった。これはいまだになぜかわかってない・・・。


CentOS:5.3
squid-2.6.STABLE21-3.el5
selinux-policy-2.4.6-203.el5
selinux-policy-targeted-2.4.6-203.el5


USBデバイスはSCSIデバイスにmapされるんだから、dmesgで確認してmountすればいいさー、と思ってたら変なところでハマってしまった。

usb-storage: waiting for device to settle before scanning
  Vendor: BUFFALO   Model: ClipDrive         Rev: 1.11
  Type:   Direct-Access                      ANSI SCSI revision: 02
SCSI device sdb: 258048 512-byte hdwr sectors (132 MB)
sdb: Write Protect is off
sdb: Mode Sense: 03 00 00 00
sdb: assuming drive cache: write through
SCSI device sdb: 258048 512-byte hdwr sectors (132 MB)
sdb: Write Protect is off
sdb: Mode Sense: 03 00 00 00
sdb: assuming drive cache: write through
 sdb: sdb1
sd 4:0:0:0: Attached scsi removable disk sdb
sd 4:0:0:0: Attached scsi generic sg1 type 0
てな感じのログが出たのでsdb1をmountしようとしたら、

mount: スペシャルデバイス /dev/sdb1 が存在しません
と言われる。
あれー?と思って/devを見ると確かに存在しない。

で結局mknodでデバイスファイルを作ってmountした。

mknod /dev/sdb b 8 16
mknod /dev/sdb1 b 8 17

でも、以前mountしたときは最初からあったような・・・
と思って調べたら、udevdがkernelからのイベントを受け取ってruleに従って適宜作成してくれるものらしい。
知らんかった。
で、ウチのudevdはどうなっとるのだと思ってpsしてみたら、居なかった・・・・。
いつ終了しちゃったんだろう・・・

ということで、
  • 一旦umount
  • USBメモリ抜く
  • /dev/sdb* をrm
  • /sbin/start_udevで改めて起動
  • USBメモリ挿す
  • /dev/sdb1出来た!
  • mount
と相成った。
しかしなんでudevd居なくなってたんやろう。yumで5.1→5.2してから再起動してないからだろうか。


OS: CentOS 5.2
udev-095-14.16.el5
kernel-2.6.18-92.1.6.el5


FC6→CentOS5.1に変えてから、graphvizを使うプログラムでエラーログが出てた。
最初は↓なメッセージだったので、
Error: Layout was not done.  Missing layout plugins?
graphviz本家からEL5用のrpmをダウンロードしてきてインストールした。
そしたら今度は、↓なメッセージ
Format: "png" not recognized.
んー、なんでじゃ。
と「graphviz format: "png" not recognized.」でgoogle検索したら2chのスレッドがヒット。
曰く、
743 名前:login:Penguin:2007/07/18(水) 04:04:48 ID:8oFxpWqq
    >>740
    CentOS4にRHEL4用のrpm入れて使ってるけど
    そんな問題起こってない。まったく問題なし。
    文字コードをUTF8に変換してTrueTypeフォント指定すれば
    日本語も出てるしね。Vine-2.6時代に四苦八苦してたのが嘘のよう。

    まさかgraphviz-gd入れてないとか言わないよな?
あ、ソレだ。
ということで、graphviz-gdもダウンロードしてきてインストール。

2chって、こういうノウハウもあるからあなどれんな~

「subversionのリポジトリブラウザとBTSとWikiが一緒になった」というtracを使ってみる。というか以前から使っていたのだが環境の問題かあちこちいじらないと動かなかったのでメモ。

当初はmod_pythonを用いようとしたのだが、Segmentation FaultまたはAbortでapacheが死んでしまった。以下の要求を満たす形で構築したい、ので試行錯誤した。

  • ブラウザだけ用意できればアクセスできるようにしたい。httpsでアクセスしたい。
  • 外から見た場合に、https://xxxx.exmple.com:2222/のようなポート番号指定のURLではなくhttps://xxxx.example.com/project/のように表現したい。→穴を開けるポートを増やしたくない。
    • ウチではサーバにlinuxを使っている。外部公開しているポイントの穴を増やすことも避けたいが、iptablesによる許可ポートもできるだけ増やしたくない。
  • 認証はapacheの機能で行いたい。
    • これは「セキュリティはインフラサイドで確保するもの」という自身のポリシーもあるけど、Active DirectoryでSubversionのリポジトリとtracの認証を共通化したかった+apacheの認証モジュールの多さと設定の柔軟さを活かしたいから、という理由
  • 外部からはhttpsで接続したい
    • プライベートなプロジェクトを管理したいから。
  • CGI型はかなりレスポンスが遅くなるので採用しない。
    • なのでmod_pythonを選択したいところだが、apacheが死んでしまう問題を解決できなかったのでスタンドアロン型を選んだ。
    • また、スタンドアロン型といっても管理するアクセスログが増えるのはイヤで、apacheのログとひっくるめて管理できるようにしたい。
で、
  • フロントエンドはapacheで、認証もここで行う。ついでにSSLも可に。
  • 内部でtracdを動かし、apache→tracd間はmod_proxyでリバースプロクシでつなぐ
という方向に決めた。
tracenv

導入

  • trac本家はここ(http://www.edgewall.com/trac/)だが、日本語化したものをインタアクト株式会社が公開しているのでありがたく使わせてもらう。
  • ClearSilver、SQLite、パイソンバインディングなどもろもろ用意せねばならんのだが、このあたりは既に詳しいページが多数あるので割愛。

設定

  • SSLの設定はあちこちに情報があるので割愛。
  • tracの設定もあちこちに情報があるので割愛。ただ、今回想定している環境は「外向きにはhttps」なので、デフォルトのままだとtracdが返す情報(特にLocationヘッダ)でhttpスキームを使われてしまうのでbase_urlを指定した。
    (projectenv)/conf/trac.ini

    [trac]
    base_url = https://外向け/trac
  • リバースプロクシは以下のような感じ。(Location内にリバースプロクシ設定を書いているので、パラメータが略されている点に注意)
    <Location /trac>
    ProxyPass http://tracdのIP:tracdのポート/trac
    ProxyPassReverse http://tracdのIP:tracdのポート/trac
    </Location>
  • 認証の設定もあちこちに情報があるので割愛。ふつーにtracのURL範囲を認証要に設定すればよい。BasicでもKerberosでも任意選択できる。
  • ここまででhttps://外向け/trac/へのアクセスがapacheにより認証されたうえで、内部で動作しているtracdにプロクシされるはず。ウチの環境の場合、内部は内部ネットワーク向けのDNSを動かしていて、外向けのFQDNと内部ホストのFQDNを同じにしているので(IPは異なる)、これが異なる場合はcookie関係の設定が必要かも。

tracユーザの識別問題

  • trac上のユーザ識別も必要だ。なぜならチケットの発行やマイルストーンの編集などの権限判断は「trac上のユーザ」で行われるから。したがってapacheで認証したユーザをなんとかしてtracdにも認識させたい。tracdで使う認証がBasicまたはDigestであれば、apacheとtracdの間で認証データベースを共有することで解決できる。しかし今回のように「BasicでもDigestでもなくKerberosが使いたい」「mod_proxyを介している」という条件が加わると、tracdの認証オプションだけは解決できないようだ。
  • で、「apacheで認証したリクエストだけがtracdに到達する」という状況から「tracdへのアクセスは認証済み」と考える。Authorizationフィールドからユーザ名を抜き出してtracユーザとして使用することにする。
  • 下のようなパッチをあてて、tracdのコマンドラインオプションと「認証しない認証クラス」を捏造する。
    --- trac-0.9.5-ja-1/scripts/tracd   2005-12-02 10:10:17.000000000 +0900
    +++ trac-0.9.5-ja-1kai/scripts/tracd    2006-06-04 20:38:59.000000000 +0900
    @@ -16,6 +16,7 @@
     # Author: Jonas Borgstr 

     from trac.web.standalone import BasicAuth, DigestAuth, TracHTTPServer
    +from trac.web.TrustedAuth import *

     import getopt
     import locale
    @@ -56,6 +57,7 @@
         try:
             opts, args = getopt.getopt(sys.argv[1:], "a:p:b:de:",
                                        ["auth=", "port=", "hostname=","daemonize",
    +                                   "trusted-auth=",
                                         "env-parent-dir=", "basic-auth="])
         except getopt.GetoptError, e:
             print e
    @@ -66,6 +68,8 @@
                 add_auth(auths, a, DigestAuth)
             if o == '--basic-auth':
                 add_auth(auths, a, BasicAuth)
    +        if o == '--trusted-auth':
    +            add_auth(auths, a, TrustedAuth)
             if o in ("-p", "--port"):
                 port = int(a)
             elif o in ("-b", "--hostname"):
    --- trac-0.9.5-ja-1/trac/web/TrustedAuth.py 1970-01-01 09:00:00.000000000 +0900
    +++ trac-0.9.5-ja-1kai/trac/web/TrustedAuth.py  2006-06-04 20:40:22.000000000 +0900
    @@ -0,0 +1,67 @@
    +# -*- coding: utf-8 -*-
    +#
    +# This is adhoc auth?-module under tracd.
    +#
    +# If you are using tracd and external proxy(ex. mod_proxy) with some auth
    +#   method, the access for tracd is already authorized.
    +#
    +# TrustedAuth regard the user as already trusted.
    +# The user extraced from Authorization field.
    +#
    +# Author: tckz<tckz@nifty.com>
    +#
    +
    +from trac import util, __version__
    +from trac.web.api import Request
    +from trac.web.cgi_frontend import TracFieldStorage
    +
    +import urllib2
    +
    +try:
    +    from base64 import b64decode
    +except ImportError:
    +    from base64 import decodestring as b64decode
    +
    +
    +class TrustedAuth:
    +    def __init__(self, dummy, realm):
    +        self.realm = realm
    +
    +    def send_auth_request(self, req):
    +        req.send_response(401)
    +        req.end_headers()
    +
    +    def parse_auth_header(self, authorization):
    +        values = {}
    +        for value in urllib2.parse_http_list(authorization):
    +            n, v = value.split('=', 1)
    +            if v[0] == '"' and v[-1] == '"':
    +                values[n] = v[1:-1]
    +            else:
    +                values[n] = v
    +        return values
    +
    +    def do_auth(self, req):
    +        if not 'Authorization' in req.headers:
    +            self.send_auth_request(req)
    +            return None
    +
    +        user = ""
    +        if req.headers['Authorization'].startswith('Basic'):
    +            auth = req.headers['Authorization'][len('Basic')+1:]
    +            auth = b64decode(auth).split(':')
    +            if len(auth) == 2:
    +                user, password = auth
    +        elif req.headers['Authorization'].startswith('Digest'):
    +            auth = self.parse_auth_header(req.headers['Authorization'][7:])
    +            if auth.has_key('username'):
    +                user = auth['username']
    +        else:
    +            self.send_auth_request(req)
    +
    +        if user == "":
    +            self.send_auth_request(req)
    +            return None
    +
    +        return user
    +
  • tracd起動時のコマンドラインは↓のような感じで。--trusted-authの引数にカンマ区切りの3要素を指定しなければならないのは、元々tracdのadd_authメソッドに手を入れていないから。「*」部分はtracプロジェクト名。「*」にすると全部のプロジェクトが対象となる(元々の仕様)
    /usr/bin/tracd --trusted-auth '*,,' -p ポート -b localhostとか -d -e parent-dir-of-envs
ちなみにCGI型の場合、apacheで認証したユーザすなわちREMOTE_USERがtracユーザとして扱われるようで特別なことはなにも必要ない。(だけど遅い、と)

python触るのは初めてなのでもっといい書き方を教えて欲しいところだが、あんましpython好きくないかも。「元々のソースに存在するブロックに対応して追加したelseブロックがautoindentでHTが使われたために対応するブロックとして認識されずsyntax error」というのは好きになれそうもない。でもgeekには人気があるっていうよね。

最近、Typekeyによるサインインができないのはなぜだろう?と思っていたら > The TypeKey signature is out of date (-632 seconds old). Ensure that your server's clock is correct ということだった。ntp動かしてなかったっけ・・・。時刻を補正してサインインしたらOK。
specをちびっと触ったのでメモ。
  • SQLite home pageからダウンロードしたsqlite-3.3.4.tar.gzを任意の場所に展開する。
  • sqlite-3.3.4.tar.gzを/usr/src/redhat/SOURCE/にコピーする(コピー先は環境により変わるのかな??)
  • specをビルドする過程でtclshが必要だったので、tclもインストールした。
  • 展開したディレクトリにある「spec.template」を編集して「rpmbuild -bb spec.template」
[aaa@bbb sqlite-3.3.4]# diff -u /usr/src/redhat/BUILD/sqlite-3.3.4/spec.template spec.template
--- /usr/src/redhat/BUILD/sqlite-3.3.4/spec.template    2005-12-20 02:30:55.000000000 +0900
+++ spec.template       2006-03-14 23:16:30.000000000 +0900
@@ -1,5 +1,5 @@
 %define name sqlite
-%define version SQLITE_VERSION
+%define version 3.3.4
 %define release 1

 Name: %{name}
@@ -30,7 +30,7 @@
 to develop programs that use the sqlite database library.

 %prep
-%setup -q -n %{name}
+%setup -q -n %{name}-%{version}

 %build
 CFLAGS="%optflags -DNDEBUG=1" CXXFLAGS="%optflags -DNDEBUG=1" ./configure --prefix=%{_prefix}

>>サイトトップへ

address

このアーカイブについて

このページには、過去に書かれたブログ記事のうちlinuxカテゴリに属しているものが含まれています。

前のカテゴリはjudeです。

次のカテゴリはmysqlです。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

Powered by Movable Type 4.261