PPTPのクライアント
アマゾンの EC2マシンからデータセンターの VPNへ PPTP接続してみた。マシンは chef で作ってブートストラップ(chef bootstraper for amazon-linux · GitHub、ruby は 1.9.3 に)した Amazon-linuxマシン。さらに手で「yum update」した。あと、なにがどこにあるのか分からないので locate も入れておく「sudo yum install mlocate」。
- ppp.i686 2.4.5-5.5.amzn1 amzn-main
- ppp-devel.i686 2.4.5-5.5.amzn1 amzn-main
- pptp.i686 1.7.2-8.1.1.amzn1 amzn-main
- pptp-setup.i686 1.7.2-8.1.1.amzn1 amzn-main
ということで「sudo yum install pptp」、そうすると依存性で ppp までは来る。
設定なんかは
EZ-NET: PPTP-VPN に接続する (CentOS 5.6) - Linux の使い方を参考に。ということで setup もインストールしよう「sudo yum install pptp-setup」。
そして設定をつくり、接続してみる。結構あっけなく繋がる。
[ec2-user@ip-10-46-97-227 ~]$ sudo pptpsetup --create PPTP --server <IP> --username <> --password <> --encrypt [ec2-user@ip-10-46-97-227 ~]$ sudo pppd call PPTP updetach Using interface ppp0 Connect: ppp0 <--> /dev/pts/2 CHAP authentication succeeded MPPE 128-bit stateless compression enabled local IP address 192.<> remote IP address 172.<>
結果の IP は使ってる VPNがそうなんだということ。
そしてルート情報
[ec2-user@ip-10-46-97-227 ~]$ sudo route add -net 192.<>.0 gw 172.<> netmask 255.255.255.0
EC2機からデータセンター機見えるし、データセンター機からも EC2機がデータセンター内の IP で見えるし。
ルート情報
Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface <IP> ip-10-46-97-1.e 255.255.255.255 UGH 0 0 0 eth0 ip-172-<>. * 255.255.255.255 UH 0 0 0 ppp0 192.<>.0 ip-172-<>. 255.255.255.0 UG 0 0 0 ppp0 10.46.97.0 * 255.255.255.0 U 0 0 0 eth0 default ip-10-46-97-1.e 0.0.0.0 UG 0 0 0 eth0
三行目が追加した EC2機から VPN(データセンター)へのルート情報。
EC2側のIP情報は隠してないけど、インスタンス落としたんでもうない。
PuTTYで生成した公開鍵を使う
どこで見たんだっけな、PuTTYgen で生成したキーペアについて。公開鍵を Linux機に仕込む。
ssh-keygen -i -f id_rsa.pub >> authorized_keys
ちなみに -iオプションは
-i This option will read an unencrypted private (or public) key file in SSH2-compatible format and print an OpenSSH compatible private (or public) key to stdout. ssh-keygen also reads the RFC 4716 SSH Public Key File Format. This option allows importing keys from several commercial SSH implementations.
コマンドラインのみで Dropbox
遅ればせながらDropbox(Dropbox)、で、Linuxではどうすればいいのだろう。勿論サイトに Linux版もあるのだけど GUI操作が前提の様だ。コマンドラインだけの環境ではどうしたら良いのだろう。
この辺を参考にしてみた。
- http://wiki.dropbox.com/TipsAndTricks/TextBasedLinuxInstall
- http://wiki.dropbox.com/TipsAndTricks/AlmostText-BasedLinuxInstall
Linux版の説明頁には Source からのインストールの項もあるのだけど結局 GUI操作が必要になる模様。
基本的な流れ
Dropboxのインストールは上記 GUI版では、オープンソース(GPL)のクライアントソフトをインストールする所から始まる。それが上記頁に挙げられているパッケージ。そしてその GUIクライアントの初回起動時に Web上のストレージとの同期を行うプロプライエタリなプログラムをダウンロードしてくる。という流れになってる模様。
GUI環境が無い場合の注意として、上記頁にはコマンドライン版(CLI)版の記述もある(What if I don't use Nautilus or X?、http://www.dropbox.com/download?dl=packages/dropbox.py)。上に挙げた Wiki に書かれた操作の一部をまとめたものの様だ。
全体的なこと
どうも全体的にみて、個人が一人で使うという想定の仕組みになっているような気がする。自動ダウンロードされるデーモンプログラム(やその補助類)、設定ファイルなんかはホームディレクトリ直下に配置される、.dropbox-dist, .dropbox とか。デーモンプログラムも上記 Pythonスクリプトでユーザ権限で実行する感じ。
まあ、ちょっとなんかすればマルチユーザで使う用のセッティングも出来るでしょう。
実行
- 上記 Pythonスクリプトをダウンロード
- http://www.dropbox.com/download?dl=packages/dropbox.py
- もうなんかホーム直下に置いとく
- 「python dropbox.py」
- 下記ずっとユーザ権限での実行
- コマンドのヘルプが返る、その示唆に従い
- 「python dropbox.py start」
- Dropboxデーモン入ってない、「-i」オプション付けたら、といわれる
- 「python dropbox.py start -i」
- プロプライエタリなもん持ってこなくちゃいけないけど、ときかれる
- 「python dropbox.py start」
- Starting Dropbox...Done!
- 「python dropbox.py status」
- Waiting to be linked to an account...
- ずっとかわらない
- 「python dropbox.py stop」
- 「sqlite3 .dropbox/dropbox.db 'SELECT * FROM config;'」
- なんか出てくる。host_id の値をメモる
- TextBasedLinuxInstall の示唆に従い host_id の値を Base64デコード
- どっか別のところから、普通のブラウザで下記にアクセス
- https://www.dropbox.com/cli_link?host_id=HOSTID
- HOSTID の所にそのデコードした値(の一部)
- 既に Dropbox使ってるマシンだとそっちが開いたりするので気を付ける。そのときはブラウザ変えたりマシン変えたりかな
- アカウントを訊かれたら登録済みのアカウントを答える
- そっちはもう忘れちゃっていい、けどまあ続き、Linux での接続を待ってもいいかな
- https://www.dropbox.com/cli_link?host_id=HOSTID
- 改めてインストール中の Linux で作業「mkdir Dropbox」
- ホーム直下に普通のディレクトリとして作成
- 「python dropbox.py start」
- Start した後同期が始まる、適宜 status を見るとか
こんな感じ、適宜「python dropbox.py stop」する。必要なら /etc/init.d スクリプトとか作って自働起動にしてもいいか。その辺のヒントやサンプルスクリプトも上記リンク先にあります。
同期相手の識別はインストール時に発行される一意の HOSTID を使っているという事でしょうね。その HOSTID と登録アカウントの対応付けを最初に行う、普通は GUIクライアントから行うのだけど、Webからブラウザでも出来るのでそうする。
dropbox.py のヘルプ
Dropbox command-line interface commands: status get current status of the dropboxd help provide help puburl get public url of a file in your dropbox stop stop dropboxd start start dropboxd filestatus get current sync status of one or more files ls list directory contents with current sync status
Twitterへのメールからの投稿
Twitter 始めました、(hs9587) on Twitter。
で、だ。メールを送ったら Twitter投稿してくれるサービス無いかなと。いかにもありそうだけど探すの面倒だし、自分用に作った。これで出先からの投稿が出来るようになった。
環境というか方針としては、CentOS で Postfix の SMTPサービスが動いてる所にメールを送り、それを Rubyスクリプトに渡してhttp://apiwiki.twitter.com/Twitter-REST-API-Method%3A-statuses%C2%A0updateをどうこうする。
Postfix 辞典 (DESKTOP REFERENCE)
- 作者: とみたまさひろ
- 出版社/メーカー: 翔泳社
- 発売日: 2006/06/21
- メディア: 単行本
- クリック: 14回
- この商品を含むブログ (7件) を見る
Postfix が特定のアドレスへのメールを捕まえる
「Postfix 辞典」逆引きリファレンス27「外部コマンドを利用したい」を参考に「transport_maps = hash:/etc/postfix/transport」の設定をする。
/etc/postfix/transport
twitter-update@<サーバアドレス> twitter_api: twitter-timeline@<サーバアドレス> twitter_api: twitter-mentions@<サーバアドレス> twitter_api: twitter-user@<サーバアドレス> twitter_api:
取り敢えず twitter-update しか実装してないけどタイムラインぐらい将来取りたいのでキーワード書いとく。
あと、これらのアドレスが有効になるのは、「transport_maps = <云々>」の設定と同様に /etc/postfix/main.cf に「local_recipient_maps =」として(= の右辺は無し)任意の @左辺アドレスを有効にしているから。そもそもなぜそうしてるかというと、それはまあいろいろある。そちらのメールアドレス名前空間からはこの4つの名前を奪った事になる。
書き換え後は「sudo /usr/sbin/postmap /etc/postfix/transport」を忘れずに。
それを Postfix から外部コマンドへ渡す
上記キーワード「twitter_api:」は転送エージェントの指定と言う事になっている、それは下記に定義したの。
/etc/postfix/master.cf
twitter_api unix - n n - - pipe user=<ユーザ名> argv=/home/<ユーザ名>/projects/twitter_api.rb ${sender} ${recipient}
最初 master.cf での定義と思わず main.cf に書いててはまった。いろいろエラーになったり或は何も起こらなかったり、ログを見れば上記 transport でメール捕まえてはいるのだが twitter_api 見付らないとエラーになってたり。
設定は /etc/postfix/master.cf です、「Postfix 辞典」逆引きリファレンス27「外部コマンドを利用したい」の記述はちょっとわかり難かった。
改行の作法とか、「unix - n n - - pipe」の項目については適宜 Postfix の資料を見よ。
- 作者: 荒木靖宏
- 出版社/メーカー: オーム社
- 発売日: 2004/08/01
- メディア: 単行本
- 購入: 4人 クリック: 32回
- この商品を含むブログ (22件) を見る
${sender} ${recipient} 以外に使用できる変数は「Postfix 辞典」機能リファレンス「pipe」p.111 とか。subject はないのね、したらまあこの二つくらいか。
渡された Rubyスクリプトが Twitter API で投稿する
Rubyスクリプト側での処理の分岐は第二引数 ${recipient} を見ることにしよう。登録されてる ${sender} に応じた Twitterアカウントで Twitter REST API に出掛ける。取り敢えず認証は甘い、まあ、自分専用だし。変なのが来る様ならブロックしましょう(それで間に合うのか、間に合うといいな)
メール内容は標準入力でやってくる。はじめ subject を Twitter投稿内容にすることも考えたが、subject なので Base64エンコードされてる。なので本文一行目(JISコードというか、ISO-2022-JP)を投稿する事にしよう。
#!/usr/bin/ruby # -*- coding: utf-8 -*- require 'nkf' require 'net/http' Net::HTTP.version_1_2 Trusted = [ '<投稿者メールアドレス>', ] Twitt = Struct.new :acount, :password Twitts = { '<メールアドレス@の前>' => Twitt.new('<Twitterアカウント>', '<Twitterパスワード>') } sender, recipient, = ARGV File.open('/home/<ユーザ名>/projects/'+Time.now.strftime('%Y%m%d%H%M%S'), 'w'){ |f| f.puts sender, recipient, '' if Trusted.include? sender then #File.open('/home/<ユーザ名>/projects/'+Time.now.strftime('%Y%m%d%H%M%S'), 'w'){ |f| f.puts ARGV, $stdin.read } twitt = Twitts[sender.split('@')[0]] case recipient when 'twitter-update@<サーバアドレス>' then null_line = false doing = '' $stdin.readlines.each do |line| (doing = line.chomp; break) if null_line null_line = true if 1 == line.length end # $stdin.readlines.each do |line| f.puts doing request = Net::HTTP::Post.new('/statuses/update.json') request.basic_auth twitt.acount, twitt.password response = nil Net::HTTP.start('twitter.com',80) do |http| response = http.request(request, "status=#{NKF.nkf('-Jw', doing)}") end # Net::HTTP.start('twitter.com',80) do |http| f.puts response.body else end # case recipient else# if Trusted.include? sender f.puts $stdin.read end # if Trusted.include? sender }
初め openuri でどうかなと思ったけど、Post だし基本認証だし Net::HTTP を直接使う。あと、gem にも Twitterクライアントっぽいもの幾つかあるっぽいのだけど、よく分からないので全部手で書いた。
メール本文の一行目、空行の次の行を見分ける所どうでしょう。メール全体をパースしたりしないでいいよね、でもちょっと手抜き過ぎか。
日本語は最初化けっぽかった、NKFでユニコードにしたらなんとか。
Trusted配列と、Twittsハッシュを二つ持ってる必要は無いよね、ハッシュに(キーが)あるなら OK とかそういうロジックで良い筈。
課題とか
そもそも自前で自由に出来る SMTPサービス(Postfixサーバ)があるという前提だし、大仕掛けに過ぎるような気もする。foward処理を頑張ればここまで仕掛け大きくしなくても良い様な気もする。いかがでしょうか
transport設定いじるという大仕掛けの割りに Rubyスクリプトをユーザホームディレクトリに置いてるのも不釣合いかな。まあ、そんな特権的なユーザなんだという風に解釈しましょう。
あとは Rubyスクリプトで、${recipient} による処理の分岐やタイムラインの取得、と、それを ${sender} に送るとか。かな。
上記スクリプト自体もリファクタリングの余地あるよね、ちょっと、いろいろ、大分。