顯示具有 網路 標籤的文章。 顯示所有文章
顯示具有 網路 標籤的文章。 顯示所有文章

2016/06/07

Socket Options

開發網路程式的朋友都應該用過socket,而socket中除了基本的方法與屬性外,還有不少options。如果觀察Socket的JavaDoc,你一定會發現有很多關於SO_XXXX、IP_XXXX、TCP_XXXX之類的屬性。這些屬性多半與通訊的連線成功或傳輸關係不是那麼大。但是,如果程式需要關注到效能,那這些屬性就會扮演重要的角色。

從Java的角度來檢視一下這些options:


IP_TOS


TOS(Type-Of-Service)的值必須介於[0..255]間。RFC 1394中則定義了下列

  • 0x00 -- normal service
  • 0x02 -- minimize monetary cost
  • 0x04 -- maximize reliability
  • 0x08 -- maximize thrughput
  • 0x10 -- minimize delay

程式可依需要將這些值做bitwise運算,來設定通訊時的等級(例如0x14是指minimize delay and maximize reliability)。
不過並不是所有的設備都會依照這個option的設定來進行傳輸,但是有需要還是可以設上。

SO_LINGER

linger是拖延的意思,這會影響Socket.close()的速度。
如果觀察TCP State Diagram,當我們做close socket的動作時,連線兩端還是會做許多複雜的動作。其中active close這端在TIME_WAIT會等待 2*MSL (Maximum Segment Lifetime)的時間,來確保送出的資料可以被另一端接收到。在RFC 793中提到了MSL是120秒。不同的OS與應用會去調整這個值,目前多數的Linux、BSD及Windows是30秒。

對於寫server-side程式的人來說,linger時間太長,你的程式雖然已經close這個socket了,但是在底層並沒有真的關掉,還在TIME_WAIT的狀態,造成了程式在短時間內沒有辦法再bind到這個port。
現在的internet速度與穩定性已經比早年好太多了,應該不需要這麼長的linger time了。如果你的程式需要較多的socket開關操作時,可以考慮把linger time設小一點。

如果把linger time設為0呢?則程式會送出設有RST flag的封包給對方,可以達到快速結束連線的效果。但是,對方的程式可能會發生 "Connection reset by peer" 的錯誤。

SO_TIMEOUT

這個時間是Socket.getInputStream().read()會被block的等待時間長度。如果read等待超過這個時間長度,則會丟出java.net.SocketTimeoutException。
SO_TIMEOUT的值須大於0,若為0,則視為無止盡。
這個值設太小,就容易常發生timeout的現象;若設太大,有時程式又會被block太久,反應速度變長。所以如何拿捏就要看應用類型而定了。

SO_SNDBUF / SO_RCVBUF

對底層的傳送/接收緩衝區大小的建議值。
這只是建議值,底層會依照所設定的值,在參照實際系統狀況來決定這兩個緩衝區的大小。
前輩建議,如果是在通訊較不好的環境,或是瞬間傳送的速度很快,那SO_SNDBUF可以設大些,這樣可以確保TCP sliding window夠大,足以容納一值無法成功送出的資料。
如果是電腦的處理速度慢,那SO_RCVBUF就要設大些,免得來不及處理,資料掉了。

SO_KEEPALIVE

如果socket建立了,但是長時間(2小時,視OS實作而定)沒有進行資料傳送,這個連線很可能會被中間的某個網路設備中止。為了避免這情形發生,如果啟用了SO_KEEPALIVE,則socket會自動發出一個keepalive probe給對方,對方也會回應回來,讓網路設備知道這個連線仍在使用中。
對有些應用或環境來說,2小時真的太長了(尤其是行動網路,有些系統商大概不會讓你站用連線這麼久),而且對Java也無法變更改時間值,所以許多應用就會自己實作ping/pong的機制來當作keep-alive。

SO_OOBINLINE

當連線有許多資料排隊要送時,如果有一緊急事件要插隊通知對方,就可以用 OOB (Out-Of-Band) Inline。啟用SO_OOBINLINE,並可透過Socket.sendUrgentData來即時送出 1-byte的資料給對方。
不過,直到Java 8,都沒有看到可以接收urgent data的方法。所以...

TCP_NODELAY

在提這項之前,要先瞭解Nagle's algorithm。簡單的說,想想一家貨運公司,如果一收到小貨物就馬上出車送貨,對公司來說整個營運效能就不高,對整個道路來說就會增加車次,容易造成路上塞車。
若是貨運公司將這些收到的小貨物累積到一定的量才出車送貨,那公司的營運效能才能提高,不會造成浪費。但是這就會造成最前面的幾件貨物要等很久才會被送出。
TCP_NODELAY就是停用Nagle's algorithm,來提高throughput。
如果所開發的系統常會傳送小資料,這個選項就該納入考慮。


以上做為工作上的紀錄,方便未來查閱。也希望對大家都有些幫助。

2014/06/11

OpenSSL CCS Injection Vulnerability

OpenSSL新公布一項針對CCS Injection Vulnerability的安全建議

此次漏洞是由KIKUCHI Masashi發現(lepidum.co.jp),影響的範圍有OpenSSL SSL/TLS 0.9.8, 1.0.0, 1.0.1。根據KIKUCHI Masashi指出,這個bug已存在達16年

KIKUCHI Masashi在下列網頁有對此弱點做詳細說明:網頁1,網頁2


此次弱點是發生在SSL handshaking phase 4的CCS。要瞭解SSL的handshaking,可以參考這些文件
文件1 ,文件2 ,文件3

2014/04/15

OpenSSL的HeartBleed漏洞

最近OpenSSL的HeartBleed漏洞鬧得沸沸揚揚,讓很多使用者與開發者都心存恐懼。那到底什麼是HeartBleed漏洞?

從SSL/TLS的heartbeat機制講起
OpenSSL是SSL/TLS protocol的實作之一。目前這個漏洞也要從這個通信協定談起。詳細的內容大家可以參考wiki的文章,這裡不多做贅述。一般使用者最常使用到的應該就是其上層的https協定了。

當通訊的兩端建立起安全通道(secure channel)後,為保持此通道不會被結束,client端可以送heartbeat信號給server,而server則會回應給client。
如下圖,client會先送任意的內容及此內容的長度給server,server會再將此內容與長度回覆給client。這個內容的最大長度是64K bytes。



這種heartbeat機制是很常用的機制,很多協定或應用都會使用這樣的機制。但為什麼OpenSSL出了問題?

首先,OpenSSL只有1.0.1 ~ 1.0.1f這幾個版本有問題,之前的版本並沒有問題,之後的版本也修復了這問題。

其次,出問題是因為OpenSSL在實作上的問題,不是SSL/TLS通信協定的問題。
OpenSSL在實作上會開一個64K bytes的buffer space,供來自所有clients的通訊共用。當有來自client的heartbeat時,OpenSSL會將送來的內容寫到此buffer,再將符合長度的內容由此buffer回傳給client。
於是,這就產生了問題。如下圖,當有心的client送的內容只有5 bytes長,卻宣稱有25 bytes;OpenSSL server並沒有去查真正的內容是多少,完全信任client所宣稱的長度,所以會老老實實的送回25 bytes的資料給client。



我們可想想,如果client只送1-byte的內容,卻宣稱長度有64K bytes,則等於獲得了整個buffer的內容。再從這裡去過濾所得到的內容,或許就可以得到其他clients與server間的對話內容。(想想網路銀行、購物網站等等,他們不都是用https來傳送你的銀行帳號、信用卡號、識別碼...等等的機密或隱私資料嗎)

雖然對有心人來說,很難預測可以從這64K bytes中取得什麼資料,不過不斷地送heartbeat,再透過程式來自動過濾擷取到的資料,還是可以撈到不少有用的資料。

既然事情發生了,怎麼解決?
對server side的管理者來說,先看看有沒有使用OpenSSL,而且是1.0.1~1.0.1f這幾個版本。如果是,那就儘快換掉。
對client使用者來說,你也不知道那些server是用OpenSSL 1.0.1~1.0.1f這些版本。最好是跟相關網站確認他們有沒有這樣的漏洞以及該如何處理。如果資料已被拿走了,最好的方法可能就是把密碼、信用卡等等的趕快換了。

參考1
參考2