My/Ham/Log (2)

チク

タレこむ

リークする

のっけから物騒なリンクを並べてしまったけど、密告して足が付かないのはどれでしょう?

足がつくのは、それぞれのサーバーでログが取られているからだ。Webにアクセスすれば、どこからやって 来て、何を持って行ったか記録されちまう。

暫く前、ビデオをユーチューブに上げて大騒ぎになったけど、サツがログの提供を求めて、そこから投稿 場所を特定してたな。

世界の密告場所には、足が付かないような工夫が凝らされている。だって、タレこんだ人を特定されちゃうと 消されてしまう恐れがあるからだ。これ、推理小説の読みすぎじゃなりませんぜ。

そこで使われてるのが、これだ。ログが取られていても、糞の役にも立たないようにしちゃう仕組みだ。

NAME
       tor - The second-generation onion router

SYNOPSIS
       tor [OPTION value]...

DESCRIPTION
       tor  is  a connection-oriented anonymizing communication service. Users
       choose a source-routed path through a set of  nodes,  and  negotiate  a
       "virtual  circuit"  through  the  network, in which each node knows its
       predecessor and successor, but no others. Traffic flowing down the cir-
       cuit  is  unwrapped  by a symmetric key at each node, which reveals the
       downstream node.

       Basically  tor  provides  a  distributed  network  of  servers  ("onion
       routers"). Users bounce their TCP streams -- web traffic, ftp, ssh, etc
       -- around the routers, and recipients, observers, and even the  routers
       themselves have difficulty tracking the source of the stream.

玉ねぎルーター。面白い事を考えるものだ。

log

前回の記事で説明が残っていた部分。下記は、cgiスクリプト。名前はlog。

#!/usr/local/bin/python -u
# -*- coding: utf-8 -*-

import cgi
import cgitb; cgitb.enable()
import sqlite3
import conf

print( conf.HEAD.format(conf.YOUR_CALL) )
print( conf.BODY )

con = sqlite3.connect(conf.YOUR_CALL + ".db")

con.executescript("""CREATE TABLE IF NOT EXISTS qsolog(
utc      timestamp,
callsign TEXT,
rcvd     TEXT,
send     TEXT,
band     TEXT,
mode     TEXT,
comment  TEXT);""")

form = cgi.FieldStorage()
if form.has_key('callsign') and form.has_key('rcvd') and form.has_key('send'):
    callsign = unicode(form['callsign'].value.upper(),"utf-8")
    rcvd = unicode(form['rcvd'].value,"utf-8")
    send = unicode(form['send'].value,"utf-8")
    band = unicode(form['band'].value,"utf-8")
    mode = unicode(form['mode'].value,"utf-8")
    if form.has_key('comment'):
        comment = unicode(form['comment'].value,"utf-8")
    else:
        comment = ''
    cur = con.cursor()
    try:
        cur.execute("INSERT INTO qsolog VALUES(datetime('now'),?,?,?,?,?,?)",
                    (callsign,rcvd,send,band,mode,comment))
        con.commit()
    except:
        con.rollback()
    finally:
        cur.close()


con.row_factory = sqlite3.Row
cur = con.cursor()
result_count = 0
try:
    for row in cur.execute("SELECT * FROM qsolog ORDER BY utc DESC"):
        print( conf.RESULT.format( row['utc'].encode('utf-8'),
                                   row['callsign'].encode('utf-8'),
                                   row['rcvd'].encode('utf-8'),
                                   row['send'].encode('utf-8'),
                                   row['band'].encode('utf-8'),
                                   row['mode'].encode('utf-8'),
                                   row['comment'].encode('utf-8') ))
        result_count += 1
        if conf.RESULT_LIMIT <= result_count:
            break
finally:
    cur.close()
    con.close()
print( "</body></html>" )

このスクリプトに輸入してる cgitbは、cgiがエラーを起した時、ブラウザーにエラーログを表示させる 便利な仕組みです。これで、保険を掛けています。

confは、設定を書いたモジュールだ。肥大化したhtml用括弧は見苦しいので、外に追いやっている。 (最後の部分でタグがちょいと出てるけど、これはご愛嬌)

後は、初めてアクセスが有った時、gsologと言うテーブルを作成。ブラウザーから送られてきたデータに コールサインと送受したRSTが揃っていたら、データベースに登録。

交信時間は、データベースに登録した時間って事にしてるけど、よく考えたら交信終了時間で登録されるな。 これでもいいのかな? それと日時はutcで記録してます。現地時間で記録したい時は、 datetime('now','localtime')としてください。

続いて、カーソルを開き、最新のデータを表示してます。row_factory を設定しておくと、DBのフィールド名で アクセス出来るので、便利です。

以上、Webアプリではお馴染みの、CRUD(作成、参照、更新、削除)のうち、ほんの基本を押さえて(試して) みました。

BandとかModeは、一応入力する事にしてるけど、こんな情報はRigから取り出すに限るな。人間が入力する もんじゃ無い。RigからBandを取り出すとしたら、7MHz帯なんて大雑把なものでなくてもいいだろう。そう すると、データベースのフィールドは、REALの方が好ましいかな。

あれ? データベースのファイルってバイナリーだけど、エンディアン方面はどうなってるのかな? おいらWindowsはおろか、Wintelが嫌いなんで、スパアクな石でもそのままデータベースファイルだけ 持って行って動けば嬉しいんだけど。(その前に、もうスパアクの石は、風前の灯って言う問題があるな)

なんか、アップル帝国の石も、インテルになっちまったからなあ。A6プロセッサーに期待するか。と言っても こんな田舎じゃ、電波が入らんしな。もう、一生、アップルの製品とは縁が無いだろうな。

ああ、大事な事忘れておったわ。一気呵成にスクリプトを書いちゃったからなー。入力した値の正当性は どうやって検証しようや? RSTなら、

[1-5][1-9]?[1-9]

ぐらいの正規表現で良かろうけど、CallSignは、どうすべ?

conf.py

次は、設定ファイルです。設定ファイルのくせに、.pyが付いているのは、私がサボりたい為です。 15年前からの基本技になってます。

# -*- coding: utf-8 -*-

YOUR_CALL = 'JA8IOC'
RESULT_LIMIT = 10

HEAD = '''Content-type: text/html; charset=utf-8"
Pragma: no-cache"
Cache-Control: no-cache"

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-Control" content="no-cache">
<title>{0}'s Log</title>
</head>
'''

BODY = '''<body>
<form method="POST" action="./log">
<table>
<tr>
  <td><b>CallSign</b></td>
  <td><input type="text" name="callsign" size="12" value=""></td>
</tr>
<tr>
  <td><b>Rcvd RST</b></td>
  <td><input type="text" name="rcvd" size="4" value=""></td>
</tr>
<tr>
  <td><b>Send RST</b></td>
  <td><input type="text" name="send" size="4" value=""></td>
</tr>
<tr>
  <td><b>Band</b></td>
  <td><input type="text" name="band" size="6" value="7"></td>
</tr>
<tr>
  <td><b>Mode</b></td>
  <td><input type="text" name="mode" size="6" value="CW"></td>
</tr>
<tr>
  <td><b>comment</b></td>
  <td><input type="text" name="comment" size="60" value=""></td>
</tr>
<tr>
  <td colspan="2"><input type="submit" value="Register"><input type="reset" value="clear"></td>
</tr>
</table>
</form>
'''

RESULT = '''
<hr>
<pre>{0}   {1} {2} {3}    {4} {5}  {6}</pre>
'''

設定ファイルと言っても、設定する箇所は、YOUR_CALLとRESULT_LIMITぐらいでしょうかね。前者は、もろに そのままですな。DBの名前にも使っています。後者は、参照結果を何局分表示するかの設定です。この 局数のリミット値は、python側のの定数として使ってるけど、SQL構文の中で、LIMIT句と共に 使った方が良かったかな?

Windowsユーザーは、スクリプト名にサフィックスが必須(と言う、アホ仕様の為)なので、formのタグ内を 変更してください。

なお、参照結果の表示が気にいらんと言う人は、RESULTの中をご自由にいじってください。なにぶん、 おいらは、見えればいいじゃんと言う無骨な人ですんで。

ログ

サーバーを起動して、アクセスすると、こんなログが取られます。見慣れた、apacheと同じ形式のログ ですな。(転送サイズは省略されてるけど)IEとかFirefoxでアクセスすると、 favicon.icoをクレクレって 五月蝿いんですけど、幸い、清貧なブラウザーを使ったので、そんな要求はされませんでした。 faviconってM$が広めた、悪しき習慣ですよ。

冒頭で書いたログってのは、こういうもんです。localhostってなってるのが、実際にアクセス してきたホストです。サツは、これを手がかりに、どこのネカフェか調べる訳です。

[sakae@cdr ~/my]$ ./server.py
Serving HTTP on 127.0.0.1 port 54321 ...
localhost - - [15/May/2011 12:24:23] "GET /ham/log HTTP/1.0" 200 -
localhost - - [15/May/2011 12:25:11] "POST /ham/log HTTP/1.0" 200 -
localhost - - [15/May/2011 12:30:17] "POST /ham/log HTTP/1.0" 200 -
localhost - - [15/May/2011 12:33:05] "POST /ham/log HTTP/1.0" 200 -

これ、ヤバイから、パッチ当てて、ログが出ないようにしちゃおうかな! と言うような、善良な サーバー管理者ばかりだと良いんですけどね。みんな律儀に、ログを取ってますからねぇ。

画面のダンプ

普通の人なら、ここん所、IEか何かの窓をキャプチャしたやつを画像で貼り付けるんでしょうけど、 おいらは、端末Loveなもんで、w3mからのやつをAAしときます。

CallSign [jr4qrz      ]
Rcvd RST [    ]
Send RST [    ]
Band     [7     ]
Mode     [CW    ]
comment  [                                                            ]
[Register][clear]

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

2011-05-15 03:30:17   JA0ZZZ 599 599    7 CW  試験ですよ

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

2011-05-15 03:25:11   8J1RL 599 589    7 CW

裏側

表の華やかな画面の裏で、こんなのをひっそりとブラウザーが記録してます。

Information about current page

Title             JA8IOC's Log
Current URL       http://localhost:54321/ham/log
Document Type     text/html
Last Modified     unknown
Document Charset  [Unicode (UTF-8)             ]
                  [Change]
Number of lines   12
Transferred bytes 1197
                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Header information

HTTP/1.0 200 Script output follows
Server: SimpleHTTP/0.6 Python/2.6.6
Date: Sun, 15 May 2011 03:25:11 GMT
Content-type: text/html; charset=utf-8"
Pragma: no-cache"
Cache-Control: no-cache"

ありゃら、しっかりPythonって広告してるよ。それにバージョンまで、ユーザーに公開しちゃってるな。 この部分も消しておきたいね。これ、基本の基ですからね。