2014年2月20日 星期四

當 MicroUSB <-> USB 傳輸線一條不用 25 元時...

MicroUSB <-> USB

記得兩三年前看過一則影片是在講經濟學的事情:
當貧富差距越大時,奢侈品的花費 >> 民生必需品
例如在看一場電影是要花很多錢,但吃一頓飯則不用,這不是國家很貧窮,而是貧富差距大,導致只有有錢人才可以看電影院,為了電影院的營運,只好收費提升。然而,正當我在路邊攤看到手機傳輸線兩條賣 50 元時,我開始在想,智慧手機是不是變成民生用品啦?既然我路邊攤買的到一條 25 元,那肯定有地方賣更便宜...

於是我找一下露天...果真如此...一條 1M 的只賣 9元 XDDD

當這種 USB <-> MicroUSB 傳輸線已經進入像牙籤、口罩、牙刷等民生用品的價碼時,站在經濟學的角度,是不是有什麼慢慢顯現了?搜尋露天:彩色麵條

彩色麵條

[Linux] 使用 MAXMIND GeoLite2 Free 進行 Offline 查詢 IP 與 Country 和 City 對應 @ Ubuntu 12.04

使用 MAXMIND DB 進行 Offline 查詢 IP 與 Country 和 City 對應

雖然網路上還有不少可以線上查詢的服務,將 IP 轉成地區資訊,如:

$ curl ipinfo.io/8.8.8.8
{
  "ip": "8.8.8.8",
  "hostname": "google-public-dns-a.google.com",
  "city": null,
  "region": null,
  "country": "US",
  "loc": "38.0000,-97.0000",
  "org": "AS15169 Google Inc."
}


不過,大多都有查詢次數的限制,所以,自己架一個來處理吧,在此就挑選 MAXMIND GeoLite2 Free 來使用,其中 FREE 版本就只提供查詢 Country 跟 City 而已。

以 GeoLite2-City.mmdb 為例:

<?php

$target_ip = isset( $_REQUEST['ip'] ) && !empty($_REQUEST['ip']) ? $_REQUEST['ip'] : ( isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : NULL ) ;
// $target_ip = '8.8.8.8';

require( 'MaxMind/Db/Reader.php' );
require( 'MaxMind/Db/Reader/Decoder.php' );
require( 'MaxMind/Db/Reader/InvalidDatabaseException.php' );
require( 'MaxMind/Db/Reader/Metadata.php' );

$reader = new MaxMind\Db\Reader('/path/GeoLite2-City.mmdb');
$record = $reader->get($target_ip);
$reader->close();
echo "<pre>";
print_r( $record );
echo "</pre>";


其中 MaxMind 程式碼可在 github.com/maxmind/MaxMind-DB-Reader-php 下載,此外,在 Ubuntu apt-get 上也有 php5-geoip - GeoIP module for php5 可安裝。

查詢 8.8.8.8:

Array
(
    [continent] => Array
        (
            [code] => NA
            [geoname_id] => 6255149
            [names] => Array
                (
                    [de] => Nordamerika
                    [en] => North America
                    [es] => Norteamérica
                    [fr] => Amérique du Nord
                    [ja] => 北アメリカ
                    [pt-BR] => América do Norte
                    [ru] => Северная Америка
                    [zh-CN] => 北美洲
                )

        )

    [country] => Array
        (
            [geoname_id] => 6252001
            [iso_code] => US
            [names] => Array
                (
                    [de] => USA
                    [en] => United States
                    [es] => Estados Unidos
                    [fr] => États-Unis
                    [ja] => アメリカ合衆国
                    [pt-BR] => Estados Unidos
                    [ru] => США
                    [zh-CN] => 美国
                )

        )

    [location] => Array
        (
            [latitude] => 38
            [longitude] => -97
        )

    [registered_country] => Array
        (
            [geoname_id] => 6252001
            [iso_code] => US
            [names] => Array
                (
                    [de] => USA
                    [en] => United States
                    [es] => Estados Unidos
                    [fr] => États-Unis
                    [ja] => アメリカ合衆国
                    [pt-BR] => Estados Unidos
                    [ru] => США
                    [zh-CN] => 美国
                )

        )

)


查詢台灣IP:

Array
(
    [city] => Array
        (
            [geoname_id] => 1668341
            [names] => Array
                (
                    [de] => Taipeh
                    [en] => Taipei
                    [es] => Taipéi
                    [fr] => Taipei
                    [ja] => 台北市
                    [pt-BR] => Taipé
                    [ru] => Тайбэй
                    [zh-CN] => 台北市
                )

        )

    [continent] => Array
        (
            [code] => AS
            [geoname_id] => 6255147
            [names] => Array
                (
                    [de] => Asien
                    [en] => Asia
                    [es] => Asia
                    [fr] => Asie
                    [ja] => アジア
                    [pt-BR] => Ásia
                    [ru] => Азия
                    [zh-CN] => 亚洲
                )

        )

    [country] => Array
        (
            [geoname_id] => 1668284
            [iso_code] => TW
            [names] => Array
                (
                    [de] => Republik China
                    [en] => Taiwan
                    [es] => Taiwán
                    [fr] => Taïwan
                    [ja] => 中華民国
                    [pt-BR] => Taiwan
                    [ru] => Тайвань
                    [zh-CN] => 台湾
                )

        )

    [location] => Array
        (
            [latitude] => 25.0392
            [longitude] => 121.525
            [time_zone] => Asia/Taipei
        )

    [registered_country] => Array
        (
            [geoname_id] => 1668284
            [iso_code] => TW
            [names] => Array
                (
                    [de] => Republik China
                    [en] => Taiwan
                    [es] => Taiwán
                    [fr] => Taïwan
                    [ja] => 中華民国
                    [pt-BR] => Taiwan
                    [ru] => Тайвань
                    [zh-CN] => 台湾
                )

        )

    [subdivisions] => Array
        (
            [0] => Array
                (
                    [geoname_id] => 7280290
                    [names] => Array
                        (
                            [de] => Taipeh
                            [en] => Taipei
                            [es] => Taipéi
                            [ja] => 台北市
                            [pt-BR] => Taipé
                            [ru] => Тайбэй
                        )

                )

        )

)

2014年2月19日 星期三

[Linux] 使用 vnstat 監控網路流量,提供每小時、每日、每週、每月流量總報表 @ Ubuntu 12.04

vnstat

最近在用雲端服務,採用用多少資源付多少錢,其中的變動收費的就是網路流量,所以就裝一下 vnstat 來計算一下,實在很夠用!

$ sudo apt-get install vnstat

接著就可以很方便地用 command line 執行顯示了。

2014年2月18日 星期二

[Linux] MongoDB Replica Set with Auth & KeyFile @ Ubuntu 12.04

mongod shutdown error

建 cluster 不見得需要帳號管控,因為多數處在保護的網路環境,而 MongoDB 預設沒有帳密管控且帳密管控做的很簡單,分成 read-only 跟 read-write 模式。而使用認證的主因是為了遠端關掉機器,沒有認證機制的服務僅能透過 localhost 關掉服務,有一派說是透過 service mongodb stop 指令,又有一派說直接 kill process 即可,但有文章說如此容易造成問題?還是要用正式的關機流程比較妥( mongo> db.shutdownServer() )。

參考文件:
架設 Replica Set 的流程:
  1. 啟動多台 mongod --replSet set_name
  2. 挑選一台 mongod 登入
  3. 使用 rs.init() 初始化後,再用 rs.add() 加入其他 mongod 或是使用 db.runCommand({'replSetInitiate':{'members':[]}}) 一次新增
架設需要認證的 Replica Set 的流程:
  1. 用 default 模式啟動一台 mongod
  2. 建立帳號
  3. 建立 keyFile (檔案內容隨意,但需要多過6個字元)
  4. 關掉後以 --replSet set_name 與 --keyFile key_file_path 模式啟動多支 mongod
  5. 登入一台 mongod 以及完成帳號認證
  6. 使用 rs.init() 初始化後,再用 rs.add() 加入其他 mongod 或是使用 db.runCommand({'replSetInitiate':{'members':[]}}) 一次新增
上述兩者流程的差別在於後者要先建帳號後,再用 --replSet 跟 --keyFile 模式啟動。而後,為了測試就寫了隻 script 筆記一下:

未使用認證模式:

$ python replset_init.py --reset

Init DB(0), Port: 30000, Path: /home/id/data/mongodb-study/cluster/db/db-0
 $ mongod --dbpath /home/id/data/mongodb-study/cluster/db/db-0 --port 30000 --oplogSize 700 --logpath /home/id/data/mongodb-study/cluster/log/db-0.log --rest --replSet firstset

Init DB(1), Port: 30001, Path: /home/id/data/mongodb-study/cluster/db/db-1
 $ mongod --dbpath /home/id/data/mongodb-study/cluster/db/db-1 --port 30001 --oplogSize 700 --logpath /home/id/data/mongodb-study/cluster/log/db-1.log --rest --replSet firstset

Init DB(2), Port: 30002, Path: /home/id/data/mongodb-study/cluster/db/db-2
 $ mongod --dbpath /home/id/data/mongodb-study/cluster/db/db-2 --port 30002 --oplogSize 700 --logpath /home/id/data/mongodb-study/cluster/log/db-2.log --rest --replSet firstset

nohup: ignoring input and appending output to `nohup.out'
nohup: ignoring input and appending output to `nohup.out'
nohup: ignoring input and appending output to `nohup.out'

Waiting...
        localhost:30000: .....OK
        localhost:30001: OK
        localhost:30002: OK

Connect to localhost:30000

Initialize the First Replica Set:

$ monogo localhost:30000/admin
mongo> db.runCommand( {'replSetInitiate': {'_id': 'firstset', 'members': [{'host': 'localhost:30000', '_id': 1}, {'host': 'localhost:30001', '_id': 2}, {'host': 'localhost:30002', '_id': 3}]}} )

Result:
{u'info': u'Config now saved locally.  Should come online in about a minute.', u'ok': 1.0}

All is done.

server info:
 $ mongo localhost:30000/admin --eval 'printjson(rs.status())'

shutdown servers:
 $ mongo localhost:30000/admin --eval 'db.shutdownServer()'
 $ mongo localhost:30001/admin --eval 'db.shutdownServer()'
 $ mongo localhost:30002/admin --eval 'db.shutdownServer()'


使用認證模式:

$ python replset_init.py --reset --auth-key-file keyfile --auth-user account --auth-pass password

Init DB(0), Port: 30000, Path: /home/id/data/mongodb-study/cluster/db/db-0
 $ mongod --dbpath /home/id/data/mongodb-study/cluster/db/db-0 --port 30000 --oplogSize 700 --logpath /home/id/data/mongodb-study/cluster/log/db-0.log --rest
nohup: ignoring input and appending output to `nohup.out'

Waiting...
        localhost:30000: ..OK

Connect to localhost:30000

Initialize the First Replica Set:

$ monogo localhost:30000/admin
mongo> db.addUser( {user: "account", pwd:"password", roles:["userAdminAnyDatabase"] })

Add account done.

Restart the mongod:

Init DB(0), Port: 30000, Path: /home/id/data/mongodb-study/cluster/db/db-0
 $ mongod --dbpath /home/id/data/mongodb-study/cluster/db/db-0 --port 30000 --oplogSize 700 --logpath /home/id/data/mongodb-study/cluster/log/db-0.log --rest --replSet firstset --keyFile keyfile

Init DB(1), Port: 30001, Path: /home/id/data/mongodb-study/cluster/db/db-1
 $ mongod --dbpath /home/id/data/mongodb-study/cluster/db/db-1 --port 30001 --oplogSize 700 --logpath /home/id/data/mongodb-
study/cluster/log/db-1.log --rest --replSet firstset --keyFile keyfile

nohup: ignoring input and appending output to `nohup.out'
Init DB(2), Port: 30002, Path: /home/id/data/mongodb-study/cluster/db/db-2
 $ mongod --dbpath /home/id/data/mongodb-study/cluster/db/db-2 --port 30002 --oplogSize 700 --logpath /home/id/data/mongodb-
study/cluster/log/db-2.log --rest --replSet firstset --keyFile keyfile

nohup: ignoring input and appending output to `nohup.out'
nohup: ignoring input and appending output to `nohup.out'
nohup: ignoring input and appending output to `nohup.out'

Waiting...
        localhost:30000: .......OK
        localhost:30001: ...................................OK
        localhost:30002: .OK

Connect to localhost:30000

Initialize the First Replica Set:

$ monogo localhost:30000/admin
mongo> db.runCommand( {'replSetInitiate': {'_id': 'firstset', 'members': [{'host': 'localhost:30000', '_id': 1}, {'host': 'localhost:30001', '_id': 2}, {'host': 'localhost:30002', '_id': 3}]}} )

Result:
{u'info': u'Config now saved locally.  Should come online in about a minute.', u'ok': 1.0}

All is done.

server info:
 $ mongo localhost:30000/admin -u account -p password --eval 'printjson(rs.status())'

shutdown servers:
 $ mongo localhost:30000/admin -u account -p password --eval 'db.shutdownServer()'
 $ mongo localhost:30001/admin -u account -p password --eval 'db.shutdownServer()'
 $ mongo localhost:30002/admin -u account -p password --eval 'db.shutdownServer()'

2014年2月13日 星期四

翻來翻去的筆記: Proxy、VPN 和 SSH Tunnel、iptables port forwarding 混用

???

有想要翻出去,就會有人想要翻進去 XD 在指定國家內架一檯 server ,提供 proxy 、 VPN 服務,提供另一個國家連線,這是一個滿常見的做法,只是,如果國家網路掌控很威,那需要嘗試一些小手段:

前提:

自家機器 IP: localhost , 可用 local_port
指定國家 SERVER IP: x.x.x.x , target service port: xx
第二國家 SERVER IP: y.y.y.y , port forward: yy

SSH Tunnel

假設在指定國家內的 server 服務都是跑 TCP 時,如果直接連它還是不夠順,那就試試 Service over SSH tunnel 吧!

$ ssh -N -L local_port:x.x.x.x:xx x.x.x.x

如此一來,原先的服務就可以改連 localhost:local_port 代替 x.x.x.x:xx 服務。若 ssh tunnel 需要斷掉還能自動重連,在 Ubuntu 就是用 autossh ,把 ssh 指令換成 autossh 即可。若開機就執行,就寫在 /etc/rc.local,另外也用 key-pair 登入來取代密碼輸入:

$ sudo vim /etc/rc.local
su -s /bin/sh account -c 'autossh -N -f -L x.x.x.x:xx x.x.x.x'


有時候單純是 routing table 的問題,需要假藉另一個國家 y.y.y.y 當跳板,這時 TCP/UDP 都可以用 iptables 處理掉(-p tcp 或 -p udp),在 y.y.y.y 機器設定:

$ iptables -A PREROUTING -t nat -i eth0 -p tcp --dport yy -j DNAT --to x.x.x.x:xx
$ iptables -A FORWARD -p tcp -d x.x.x.x --dport xx -j ACCEPT


如此一來,連 y.y.y.y:yy 等同連到 x.x.x.x:xx 。

此外,純 TCP 在 Ubuntu 中還可以透過 redir 套件來處理,若 redir 已安裝好後,好處相較于 iptables 可以不需要 root 權限:

$ redir --lport yy --laddr=y.y.y.y --cport=xx --caddr=x.x.x.x

以 Proxy、VPN 這類服務而言,大概能搞的招數就這些吧,例如 Proxy over SSH tunnel 或甚至 SSH tunnel 是從第二國家建立,以此強制 routing 的改變。