Discuz的圖形驗証碼出不來

客戶反映,他們的獨立主機上,有Discuz的圖形驗証碼出不來的錯誤。

我們一查php生成的error檔,看到的訊息是:
PHP Fatal error:  Call to undefined function imagettftext()

看來是有少php的library。這個imagettftext()所對應的php library,是GD和freetype這兩個。所以解決之道就是:

  1. 執行cpanel的easyapache:WHM -> Software -> EasyApache
  2. If prompted to upgrade, do so then repeat the above step
  3. Begin customizing based on the current provile
  4. Proceed through the screens until you get to “Step 5”
  5. On “Step 5,” click on “Exhaustive Options”
  6. Under PHP, check the checkbox for GD, ttf
  7. Proceed with Build & Compile Process

一旦成功了,圖形驗証碼就出來了。

如何讓主機的防火牆csf不會誤擋到ftp

最近公司的客戶,用ftp連線時,一直被主機的防火牆誤判為攻擊。這個問題是這樣子產生的:公司的防火牆是用csf firewall這個套件,而這個套件如果沒有特別設定的話,對於ftp,很容易誤擋。

根據csf的文件,linux的iptables如果ip_conntrack和ip_conntrack_ftp沒有正常的運作時,FTP的被動模式就無法順利地運作。在這種條件下,我們必須設定ftp的被動通訊埠在防火牆上是被視為可連接的。

以pure-ftp為例子:
(1) 必須修改/etc/pure-ftpd.conf,取消
PassivePortRange 30000 35000
這一行的註解 (注意:此處的port range要和之後步驟,設定CSF的port range相符合)
(2) 重新啟動pure-ftp
(3) 修改csf的config檔 /etc/csf/csf.conf
在 TCP_IN中,加上30000:35000,例如:
# Allow incoming TCP ports
TCP_IN = “20,21,22,25,53,80,110,143,443,465,587,993,995,2077,2078,2082,2083,2086,2087,2095,2096,1891,30000:35000″
(4) 重新啟動csf

這樣子設定之後,防火牆才能和ftp完美的合作。

參考資料:http://www.configserver.com/free/csf/readme.txt

延伸閱讀:如何查看linux server連線port是否異常?

13. A note about FTP Connection Issues
######################################

It is important when using an SPI firewall to ensure FTP client applications
are configured to use Passive (PASV) mode connections to the server.

On servers running Monolithic kernels (e.g. VPS Virtuozzo/OpenVZ and custom
built kernels) ip_conntrack and ip_conntrack_ftp iptables kernel modules may
not be available or fully functional. If this happens, FTP passive mode (PASV)
won't work. In such circumstances you will have to open a hole in your firewall
and configure the FTP server to use that same hole.

For example, with pure-ftpd you could add the port range 30000:35000 to TCP_IN
and add the following line to /etc/pure-ftpd.conf and then restart pure-ftpd:
PassivePortRange	30000 35000

For example, with proftpd you could add the port range 30000:35000 to TCP_IN
and add the following line to /etc/proftpd.conf and then restart proftpd:
PassivePorts	30000 35000

FTP over SSL/TLS will usually fail when using an SPI firewall. This is because
of the way the FTP protocol established a connection between client and server.
iptables fails to establish a related connection when using FTP over SSL
because the FTP control connection is encrypted and so cannot track the
relationship between the connection and the allocation of an ephemeral port.

If you need to use FTP over SSL, you will have to open up a passive port block
in both csf and your FTP server configuration (see above).

Perversely, this makes your firewall less secure, while trying to make FTP
connections more secure.



如何選購外國的虛擬主機?

一般而言,選購外國的虛擬主機,台灣人的首選,是以美國、日本為主。日本的話,由於日文還是比較不比英文普遍,大多數人還是先考慮美國。

我看了許多網站評比美國的虛擬主機,說了一堆服務幾分?有沒有送google adword?身為主機商的我,我覺得,這些都不是客戶要的。客戶要的東西,對客戶而言,最重要的東西:(1)線路品質 (2)價格。其它的什麼google adword?客服如何?機器的軟体是不是最新的?這些常常都不是客戶最在意的事。

讓我來解釋一下,什麼是線路品質的觀念吧:
我們用ping這個command去連遠端的主機的話,可以得到一個數字,叫做RTT。這個數字,對於傳輸有莫大的影響。怎麼說呢? 以unethost的美國西岸主機來講,RTT約是150ms多。雖然主機本身的頻寬是100Mbps,但是,對於單一的TCP連線,考慮TCP的slow start effect & congestion control效應之後,理論上的最高速是4.3Mbps 或是500 kbyte/sec。當然,現代的瀏覽器已經有做平行的連線,一般而言最多是十條。但是平行的連線是對多個小檔,可以加速,如果是一個單一的大檔,或是說一個PHP生成的動態頁面,就一定會被這個速度所限制。

這個RTT如何影響單一連線的最高速,其實是有計算公式的。大家要是記不住,概念上是RTT愈小,單一連線的最高速限愈大。詳細推導的流程是:TCP在傳輸的時候,電腦會對每一條TCP連線生成一個Slilding window(滑動窗戶)。這個window的大小,必須等於BDP = bandwidth delay product 。也就是說,這個滑動窗戶的大小 = 頻寬 乘上 RTT。由於一般來講,大部分的人用的電腦OS是windows,內建的TCP演算法也不是最新的,所以Slilding window size是固定的:64kbytes。這種時候,頻寬就可以由 ( Slilding window size/ RTT)來算出。

而上頭,本文所講的理論上限也就是這樣子算出來的。unethost的主機測速資料在這邊

參考資料可以看下方的英文。

Sometimes, we are feeling slow Internet connection, but don’t know how we can measure the speed and what is right speed, download speed, TCP throughput, I can expect. Measuring and calculating TCP throughput is not that hard. See below famous TCP throughput formula.

RCV buffer size / RTT = Max TCP throughput = ? bps
** Buffer size is normally 65Kbps

ex) (64Kbyte x 8bit) / 0.17 = 3011764 bps = 3Mbps, (RTT=170ms)

To learn more about Internet Speed Issue, please check our article series within www.ipBalance.com

RCV Buffer size / TCP receive window size

– RCV buffer size is denoted as TCP receive window size. Window systems have 64Kbyte of window size as default (Window NT and Millennium have 8Kbytes of window size).  The TCP/IP standard allows for a receive window up to 65,535 bytes in size, which is the maximum value that can be specified in the 16-bit TCP window size field. Why 65Kbytes? Well, more accurate expression will be  65,535 = (2^16)-1. To improve TCP throughput, speed, performance whatever you called, in high speed connection or high delay network, you can increase TCP window size(reference RFC 1323). However, if transport link is not stable, it might give you worse performance. Packet loss or bottleneck in the network is the most likelyfactors that are leading to the TCP throughput reductions.

Optimal TCP window size

– Optimal RCV buffer size is considered to be 2 x BDP, where BDP is the Bandwidth * Delay Product

ex) RTT is 20 ms, and connection speed is 10 Mbps.
2 x (10Mbps/8 * .020s) = 50Kbytes

Well, default window size 65kbytes is not adequate for today’s network. In these days, most of network is 100Mbps or higher.

Round Trip Time(RTT)

– If you are not using TCP window scaling option (RFC 1323), TCP window size will be used as 64Kbytes. If then, Round Trip Time(RTT) is the main factor to decide TCP throughput between locations. 

RTT 10 ms => TCP throughput = 52428000 bps = 52Mbps
RTT 20 ms => TCP throughput = 26214000 bps = 26Mbps
RTT 50 ms => TCP throughput = 10485600 bps = 10Mbps
RTT 100 ms => TCP throughput = 5242800 bps = 5.2Mbps
RTT 150 ms => TCP throughput = 3495200 bps = 4.3Mbps
RTT 200 ms => TCP throughput = 2621400 bps = 2.5Mbps
RTT 300 ms => TCP throughput = 1747600 bps = 1.7Mbps
RTT 500 ms => TCP throughput = 1048560 bps = 1Mbps

** Used maximum TCP window size  = 65Kbytes = 65535

You can see the deficiency with the greater RTT.

 

php 5.3.10-joomla

2012年4月初,我們開始陸續升級主機上的php版本。舊版的php 5.2.17已經是deprecated了。在接連得知有客戶的網站因為php 5.2的bug問題,被駭客攻擊之後,我們決定還是要忍痛升級php 5.3.10

升級php這件事,我相信對各家的主機商都是大工程。主要也是相容性的問題。如果升級一台shared host的php,老客戶的程式出現問題,我們還是得幫忙處理。

果然,我們一升級之後,客戶的joomla程式就出現了問題:本來沒有狀況的網頁,冒出了 Warning: Parameter 1 to modMainMenuHelper::buildXML() expected to be a reference, value given in  …的字樣。

後來我們終於找到了問題,php 5.3對於語法嚴謹度的要求,比5.2還來得高。所以在 joomla的 modMainMenuHelper::buildXML() 這個函數,如果參數1傳入時,並不是用reference的型態傳入,就會造成問題。

解法是這樣子:
在檔案 /modules/mod_mainmenu/helper.php 中

修改一行,把&去掉
function buildXML(&$params)
改成
function buildXML($params)

這樣就搞定了。

 

透過.htaccess檔,禁止來自日本的ip的訪問

客戶似乎受到來自日本的壓力?(OS:被AV女優爬到身上嗎?)

總之,客戶請我們幫忙擋掉來自日本ip address的訪問。要透過.htaccess檔禁止來自日本的ip的訪問,得先上網找分配給日本的IP清單。後來湊關鍵字了湊老半天,總算不負我多年來的日本A片素養日本語能力素養。關鍵字是「日本に割り当てられているIPアドレスリスト」

這個.htaccess檔就放這邊了,有需要的請取用吧。XD

Search engine friendly URL

大約今年三月時,我把整個官網整合了whmcs系統。http://unethost.com/

這個whmcs有個功能叫做 Search engine friendly URL support,簡稱為SEF,這個是什麼意思呢?

如果不勾選這個選項的話,在knowledge base新增的文章,它的URL就會長成這個德性:
http://support.unethost.com/knowledgebase.php?action=displayarticle&id=18

很明顯可以知道這個連結是一個動態產生的頁面。然而各家的搜尋引擎google, yahoo對於分數的計算,都是比較喜歡靜態的頁面。所以,我就把這個選項勾了,然後,上頭那個連結就自動轉換成:
http://support.unethost.com/knowledgebase/18/web-template.html

到這裡為止,世界是和平的^^。然而,不和平的在後面。很快地,我就發現了很討人厭的問題,如果我新增的文章的title,全部是中文時,就會長出下方這種會爛掉的link,會爛掉的原因,似乎是因為會造成mod rewrite的loop。
http://support.unethost.com/knowledgebase/23/.html

這是為什麼呢?因為,whmcs的php在生成內部連結時,大概是長成這樣子的語法:
{if $seofriendlyurls}
announcements/{$id}/{$urlfriendlytitle}.html
{else}
announcements.php?id={$id}

其中,這個$urlfriendlytitle,被whmcs的設計者(這些死老美!!) 設計成,不考慮多語言的case,如果你的title本來是全部用中文寫的,它就真的給你丟出空字串。然後你的連結就會爛了。所以我對上述的code作了修改:


$urlfriendlytitle}.html
改成了
$urlfriendlytitle}-seo.html

這實在是個很暴力/很醜的改法。不過,先湊合著用就好~。(SEO做到1000分,服務不好還是不會有客戶)  這樣子,就不會生成.html的這種,之後會造成loop問題的連結。而是會形成:http://support.unethost.com/knowledgebase/23/-seo.html
我只要求.html之前,至少有一些字串就好了~ 不要求太多。

接下來,我就要開始動手術了:一次修改大量的.php檔,一口氣解決問題。來一個指令吧:

find . -name *.tpl  -exec grep -l urlfriendlytitle {} \;

把所有疑似有罪的檔案全部都抓出來修改。就這樣子,我讓官網的一些動態頁面,全數變成了SEF(Search Engine Friendly) url

備份主機– 使用rsyncd

有時候,會有一種需求,就是兩台獨立主機之間,常常需要做快速的遠端備分。這種時候,rsyncd的server mode就派上用場了。

server 端:
(1) 透過WHM ,去開啟873這個port的firewall

(2) mkdir /home/bk_server1
mkdir /home/bk_server2

(3) 寫好 /etc/rsyncd.conf
<pre>
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsync.lock
log file = /var/log/rsyncd.log #

[server1]
path = /home/bk_server1
auth users = bk_user
uid = root
gid = root
secrets file = /etc/rsyncd.secrets
read only = no

[server2]
path = /home/bk_server2
auth users = bk_user
uid = root
gid = root
secrets file = /etc/rsyncd.secrets
read only = no
</pre>
(4) 寫server side的密碼檔
vi /etc/rsyncd.secrets
<pre>
bk_user:XXXXXXXXXXXXXXX
</pre>

密碼檔設置完後,
chown root:root /etc/rsyncd.secrets
chmod 600 /etc/rsyncd.secrets

(5) 修改 /etc/xinetd.d/rsync
將 disable = yes 改成 disable = no

(6) service xinetd restart

(7) 確認 xinetd 有沒有去聽 rsync的 873 port
netstat -ntlp |grep 873
( 必須出現才是合理的。)

client 端:
(1) vi /root/rsyncd.secrets
注意,內容的格式和 server端的不同,只有密碼,而沒有user name
XXXXXXXXXXXXX

(2) chmod 600 /root/rsyncd.secrets

(3) 用下列的command就可以sync了。
例如,將client side的 /root,備分到 server 端的 /home/bk_server1
<pre>
rsync -avHz –password-file=/root/rsyncd.secrets /root bk_user@yourhost.com::server1
</pre>
(4) 在crontab 中,加入上述的command

用linux的top指令來抓出主機的效能瓶頸

我在Cloudlinux的網站看到的教學文。對於常常在抓linux的效能瓶頸的我,相當有幫助。linux的top指令,是常用的好東西,只是它給的資訊很多,沒有經驗的人很難立刻理解。從範例中來理解是最好的。

(*) example 1:
top – 01:49:59 up 49 min, 5 users, load average: 18.02, 32.55, 34.91
Tasks: 269 total, 1 running, 268 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.4%us, 0.6%sy, 0.0%ni, 16.7%id, 82.2%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 8028612k total, 2268460k used, 5760152k free, 88348k buffers
Swap: 4192924k total, 731688k used, 3461236k free, 309828k cached

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
8842 mysql 11 -10 1274m 178m 4076 S 0.0 2.3 0:46.40 mysqld

機器跑得很不順 ( 因為load已經上來了,居然有到18 )
發現 Cpu 82.2%wa —> I/O wait
—-> 因為io busy的process通常也是cpu busy,所以直接看第一行。
—-> 八成是第一行的process把cpu cycle 吃太多了
—-> 第一行就是 mysqld
喔,這個很正常,mysqld只要config不對,就容易有這種問題。
到mysql去找問題吧。
(*) example 2:
01:15:52 up 15 min, 4 users, load average: 28.37, 20.02, 10.44
Tasks: 762 total, 1 running, 760 sleeping, 0 stopped, 1 zombie
Cpu(s): 0.5%us, 1.8%sy, 0.0%ni, 0.0%id, 97.3%wa, 0.0%hi, 0.4%si, 0.0%st
Mem: 8028612k total, 7981536k used, 47076k free, 34512k buffers
Swap: 4192924k total, 2894460k used, 1298464k free, 272708k cached

機器跑得很不順 ( 因為load已經上來了,居然有到28 )
發現 Cpu 97.3%wa —> I/O wait
此外,還發現一件事: swap 被用掉了3G,mem幾乎被用光了
—-> 八成是有一隻process把ram吃光光了,是誰呢?
—-> 按shift +m
—-> 第一行就是吃最多ram的process

(*) example 3:
top – 01:27:59 up 31 days, 22:31, 3 users, load average: 2.36, 2.33, 4.96
Tasks: 697 total, 1 running, 692 sleeping, 0 stopped, 4 zombie
Cpu(s): 2.1%us, 1.2%sy, 0.0%ni, 50.9%id, 45.5%wa, 0.1%hi, 0.1%si, 0.0%st
Mem: 4023964k total, 3917884k used, 106080k free, 298548k buffers
Swap: 8385920k total, 504136k used, 7881784k free, 1557260k cached

機器的load沒有衝高,然而,io wait 還是不低 45.5% 。swap雖然有被用到了,但是還小於0.5G,小事啦…,mem也還剩不少 ( 不是ram的問題 )

雖然cpu busy的process 通常也是io busy,但是,目前這種情況無法直接確定
所以top的第一行,cpu用最多的process,就一定是io用最多的。

所以這種時候,會需要另一隻程式 iotop,直接殺向io bound的process,找出效能瓶頸。

awk抓成績

最近接的一個case,是東光舞蹈教室的自由盃網站維護:客戶的要求之一,是要在網站上提供17屆、18屆的比賽成績連結。跟客戶要資料時,客戶表示,在某某網站上就可以”抓”了。像這個網站

由於我太好凹了,就算了很便宜的價錢給客戶,不過是個成績網頁嘛,就是複製、貼上,修一下html,就結束了。(我是這樣想的。) 真的開始做的時候,才發現,糗大了。那個客戶叫我去抓資料的網站… 怎麼會出來的html,居然是…硬寫的。完全沒有<tr><td>。這叫我要怎麼湊啊。

後來,我想了一招:來吧, awk

cat original | awk '{if ($3!="") {print "array( " $1"," $2",\""
$3"\",\""$4"\"),"} else { if ($1!="") { print "\""$1"\"=>array("  } else
{print "\n" }  }  }'

試了一下噁心的awk指令,似乎有好一些了…
至少…打幾個字就變成可以用的code了。

"業餘組A組拉丁_決賽"=>array(
array( 名次,背號,"選手姓名一","選手姓名二"),
array( 1,138,"Patara","Melissa"),
array( 2,134,"潘彥儒","吳靜雯"),
array( 3,122,"劉漢偉","姚又齊"),
array( 4,139,"Puttipong","Sahaifa"),
array( 5,132,"鄭嘉文","石毓琳"),
array( 6,143,"賴建霖","郝偵汝"),
array( 7,144,"曾洺寘","李安洏"),
array( 8,137,"吳京橋","林婉姍"),
array( 9,145,"楊東原","陳蘭芳"),

 

CPanel developer’s note

想不到最近還是有寫程式的機會,XD
目標是:修改httpd.conf , 根據cpanel的user package,來設置cband的quota limit
algorithms:
(1) 由cpanel的api—listaccts
去抓出package ( 看是A, B, C .. )
(2) 對於每一個user
建立資料夾 mkdir -p /usr/local/apache/conf/userdata/std/2/$user
(3) 由每一個user 的package, A —> a.conf
B —> b.conf
將對應的 $package.conf 拷貝到
/usr/local/apache/conf/userdata/std/2/$user/$package.conf
(4) 重新generate /usr/local/apache/conf/httpd.conf
下command /usr/local/cpanel/bin/build_apache_conf