2012年5月31日 星期四

PHP imagettftext() could not read font

今天撞牆撞很大....由於手邊在碰的一個專案裡面需要產生類似驗證碼的圖片,他用了 imagecreate(), imagettftext(), imagesetpixel() 這些 PHP functions。聽說這支程式「曾經」是可以 work 的,不過在我手上就不 work,為了證明不是人品問題,一定要把這個 bug 修掉!
一開始我傻傻的在程式碼裡面翻找,但這樣實在太沒效率了,身為一個專業的....呃...雜工,一定要懂得善用工具!所以我用了..... command line php.....
$ php image.php > /dev/null
對啦,只不過是測試環境從 apache 換到 command line 底下了,這樣是有比較強嗎?有喔~因為我的測試環境有裝 xdebug,只要有 enable 就可以在 command line 底下看到 debugging messages,不用特別打開 stack trace。至於最後面把 standard output 導向 /dev/null 是為了不想看到他輸出的那張不完整的圖,那會干擾畫面。
首先第一步,我忘記詳細的訊息了,大意是說 imagecreate() is undefined 等等,這時候當然要去找找這函式有沒有需要什麼相依的 library 啊!找了一下發現,這些函式是由 PHP 的 GD module 所提供的,所以我迅速的安裝了 GD 模組...
$ sudo apt-get install php5-gd
接著,才是重頭戲的開始....

2012年5月30日 星期三

對 Vim 啟動過程做效能分析

昨天在噗浪上看到有趣的分享,是一篇 StackOverflow 上的文章:Profiling vim startup time
其實講的東西相當單純,就是 vim 提供了 --startuptime 選項,後面接上 log 檔的檔名,他會幫你把啟動過程中每個部份所花的時間都記錄下來,有個別時間也有累計時間。例如:

$ vim --startuptime vim.log
然後就可以看 vim.log 的內容來了解自己啟動 vim 的時候在哪個部分花最多時間囉。對於 vim plugin 裝很多又想瘦身的朋友應該很實用。:)

嗯.....身為一個程式語言 (vim script) 的 interpreter....果然會出現這種東西XD

2012年5月25日 星期五

Git on Windows 安裝筆記

Git 是一套很棒的分散式版本控制系統。不過由於它一直是在 Linux 上生長的,對於在 Windows 上使用來說其實稍嫌麻煩。在網路上搜尋通常會找到 Git for windows 跟 msysGit 這兩個不同的名詞,我過去一直沒辦法很清楚的把他們兩者區分開來。根據 msysgit 在 github 上的首頁StackOverflow 上的討論,我目前的理解是,msysGit 就是 msys + Git 的完整環境,包含了 build 程式用的 toolchain,同時他的執行檔是直接在 user (或者該說是 developer) 的機器上 compile 出來的,使用者隨時可以透過 git pull 取得最新版的 msysGit 來編譯,算是給 git 開發者用的。而 Git for Windows 可說是 msysGit 的「產出」,是預先 compile 好的 git.exe 還有其他執行檔們...其中只包含了基本的 msys 環境、有 bash、ssh、甚至 Git GUI 等工具,但是沒有 toolchain,適合 git 使用者安裝。
另外還可能會找到一個更有名的東西,稱為 TortoiseGit,這是知名專案 TortoiseSVN 的相關專案,顧名思義,就是烏龜殼包了 Git 啦!要注意的是,他只是一個 Git frontend,需要指定相關執行檔 (如 git.exe) 的位置才能工作。特別的是,他本身附帶了 PuTTY 的 ssh client (plink.exe),讓使用者可以透過比較符合 windows 使用習慣的方式來使用 ssh,如果不是很熟 linux 或是 GUI 狂熱份子可能會比較喜歡。XD
註:知名專案 cygwin 也可以安裝 git 並在 command line 下使用,但對於沒在使用 cygwin 的使用者而言麻煩得多,故此處不介紹。
這篇文章分成三個部分:首先介紹 Git for Windows (免 compile 的那個) 的安裝,接著是 msysGit (需要 compile 的那個) 的安裝,最後會介紹 TortoiseGit 的安裝,並以一個簡單的 git clone 作為結束。如果是一般單純想在 windows 上用 git 的人,可以只看第一跟第三部分即可,第二部分就當作參考資料吧!
另外報告一下我用的環境:
  • Windows 7 32bit
  • msysGit 1.7.10
  • TortoiseGit 1.7.9 32bit

2012年5月23日 星期三

「cannot open shared object file」的解決方案

有時候執行一些指令,會碰到下面這樣的訊息:

error while loading shared libraries: libiconv.so.2: cannot open shared object file: No such file or directory

在這個例子中,我們的程式找不到 libiconv.so.2 這個 dynamic library。那麼應該怎麼解決呢?

首先必須找到系統中的 libiconv.so.2,下面四條指令選一條作就好:

$ locate libiconv.so.2
$ whereis libiconv.so.2
$ find /usr /lib -name libiconv.so.2
$ find / -name libiconv.so.2 2>/dev/null

這時候就可以找出函式庫位置,例如:

/usr/local/lib/libiconv.so

萬一沒有找出來的話,就要自行安裝了。這篇文章有教該如何安裝 libiconv,如果是其他函式庫的話可以自行變通。

找到位置之後,應該怎麼做呢?如果我們有 root 權限的話,可以把函式庫所在路徑寫入 /etc/ld.so.conf,再重新產生 ld 的 cache 即可,如下:

# echo "/usr/local/lib" >> /etc/ld.so.conf # 注意! 要用 >> 而非 >!
# ldconfig

在某些系統中,/etc/ld.so.conf 可能會預設加上 include /etc/ld.so.conf.d/*.conf 這樣的敘述,那們我們也可以把路徑放在那個目錄下:

# echo "/usr/local/lib" >> /etc/ld.so.conf.d/usr_local_lib.conf
# ldconfig

這樣一來就可以讓程式順利搜尋到需要的 library 囉!

BUT!! 玩 Linux 最重要的就是這個 BUT!!

如果我們沒有 root 權限的話該怎麼辦呢?這時候只好很可憐的自己搞定了...如果需要自行編譯 library 的話,可以照著類似的步驟做,但是 prefix (也就是安裝位置) 要設定在自己的家目錄下,例如:

$ ./configure --prefix=$HOME/libiconv

但這邊假設系統中已經有 /usr/local/lib/libiconv.so.2 這個檔案,進行以下步驟:

$ echo "export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH" >> ~/.bashrc

原理很簡單,就是透過設定 LD_LIBRARY_PATH 來讓程式找得到需要的 library 檔案。修改後需要重新登入才會生效喔!

但是...基本上還是建議不要用後面這個方法啦,找你的系統管理員協助設定 /etc/ld.so.conf 才是好主意。這裡有篇文章:Why LD_LIBRARY_PATH is bad,專門在討論為什麼不要隨意使用 LD_LIBRARY_PATH

2012年5月18日 星期五

SSH 安全性設定筆記

以下收錄可增加 ssh 安全性的各種技巧,主要的修改都在 /etc/ssh/sshd_config 中,同時,修改設定後別忘了重新載入設定值或重新啟動 sshd。
  • 修改預設 port (可用多行開啟多個 port)
    Port <port>
    
  • 僅監聽特定 ip (適用於多網卡/多 IP 的情形)
    ListenAddress 192.168.1.10
    
  • 禁止 root 登入
    PermitRootlogin no
    
    管理者必須先以個人帳號登入,再 su 成 root,或利用 sudo 工作。
  • 禁止使用空密碼登入
    PermitEmptyPasswords no
    
  • 僅允許或拒絕特定帳號或群組登入
    AllowUsers <user1> <user2> <user3>
    AllowGroups <group>
    DenyUsers *
    DenyGroups no-ssh
    
    根據實驗,對於同一帳號而言,如果同時 Allow 跟 Deny 的話,結果會是 Deny 的。
  • 廢除密碼登錄,強迫使用 RSA/DSA 驗證
    RSAAuthentication yes
    PubkeyAuthentication yes
    AuthorizedKeysFile %h/.ssh/authorized_keys
    PasswordAuthentication no
    
    並確保 user 的 ~/.ssh 權限為 700,同時將該 user 的 public key 加入其 ~/.ssh/authorized_keys 中。Public key 的產生方式可搜尋 ssh-keygen
  • 僅允許 SSHv2
    Protocol 2
    
  • 限制特定使用者、群組、主機或位址的登入行為,這裡以限制 somebodyhandsomebody 不可使用密碼登入為例
    Match User somebody,handsomebody
    PasswordAuthentication no
    
    但是要怎麼結束 Match block 我只找到有資料說「In sshd_config, Match blocks must be located at the end of the file.」,如果真是這樣,那就只好認了。
  • 使用 TCP wrappers 限制來源 IP
    # vim /etc/hosts.deny
    sshd: ALL
    # vim /etc/hosts.allow
    sshd: 192.168.1 1.2.3.4 # 僅允許 192.168.1.* 與 1.2.3.4 連線
    
  • 使用 iptables 限制來源 IP
    # iptables -A INPUT -p tcp -m state --state NEW --source 1.2.3.4 --dport 22 -j ACCEPT
    # iptables -A INPUT -p tcp --dport 22 -j DROP
    
    設定會立即生效,若希望重開機後還能保存,需要手動儲存 iptables 的設定。
  • 時間鎖定 (這段直接引用並修改原作者的文字,有空再消化整理)
你可以使用不同的iptables參數來限制到SSH服務的連接,讓其在一個特定的時間範圍內可以連接,其他時間不能連接。你可以在下面的任何例子中使用 /second/minute/hour/day 開關。
第一個例子,如果一個用戶輸入了錯誤的密碼,鎖定一分鐘內不允許在訪問SSH服務,這樣每個用戶在一分鐘內只能嘗試一次登陸
  # iptables -A INPUT -p tcp -m state --syn --state NEW --dport 22 -m limit --limit 1/minute --limit-burst 1 -j ACCEPT
  # iptables -A INPUT -p tcp -m state --syn --state NEW --dport 22 -j DROP
第二個例子,設置iptables只允許主機193.180.177.13連接到SSH服務,在嘗試三次失敗登陸後,iptables允許該主機每分鐘嘗試一次登陸
  # iptables -A INPUT -p tcp -s 193.180.177.13 -m state --syn --state NEW --dport 22 -m limit --limit 1/minute --limit-burst 1 -j ACCEPT
  # iptables -A INPUT -p tcp -s 193.180.177.13 -m state --syn --state NEW --dport 22 -j DROP
  • 檢查相關檔案權限,不安全則不允許登入
    StrictModes yes
    
    某些相關檔案權限設定若有錯誤時,可能造成安全性風險。如使用者的 ~/.ssh/authorized_keys 權限若為 666,可能造成其他人可以盜用帳號。
  • 自訂使用者登入時顯示的 banner (話說這跟安全性有什麼關係...? 大概可以用社交方式嚇跑壞人吧...= =a)
    Banner /etc/ssh/banner # 任意文字檔
    
  • 限制 su/sudo 名單
    # vi /etc/pam.d/su
        auth       required     /lib/security/$ISA/pam_wheel.so use_uid
    # visudo
        %wheel  ALL = (ALL) ALL
    # gpasswd -a user1 wheel
    
  • 限制 ssh 使用者名單
    # vi /etc/pam.d/sshd
        auth required pam_listfile.so item=user sense=allow file=/etc/ssh_users onerr=fail
    # echo <username> >> /etc/ssh_users
    

參考文章列表