2011-07-01 132 views
0

我正在C#上開發一個服務器(使用*異步方法)。一切正常,直到一方違反協議(例如服務器攻擊)。協議錯誤套接字服務器

以下結構的客戶端和服務器交換消息:

  1. 前4個字節定義以字節
  2. 消息體的長度(N)以下的N個字節定義消息體

如果有人發送錯誤的長度 - 此客戶端和服務器之間的所有通信變得不可預測。

所以這個想法是創建一個最簡單的方法自同步協議。

我正在使用TCP協議,所以我的想法是將消息分解成數據包,並且沒有兩個消息應該共享相同的數據包 - 這樣我就可以忽略協議違規並恢復通信,如果有的話出錯。

我想爲此使用TCP,因此數據包將與TCP段相同。但也有少數漁獲:

  • 的MTU(其定義了MSS)可能會有所不同,並沒有爲緩衝區大小沒有規定值I可以使用(糾正我,如果我錯了)
  • 我不能」 t找到直接處理TCP段的方法(沒有「流」抽象)

我是socket服務器編程的新手,所以我需要幫助。也許有人可以共享這個問題的常見解決方案(防故障協議),或者描述常見的陷阱,或者提供有用的鏈接。

我在.NET下開發,如果可以避免,我不想使用任何P/Invokes。

回答

2

TCP的抽象是甲流,沒有內置的消息邊界,你不應該試圖違反該抽象。

處理行爲不端客戶端的主要策略是嚴格檢查客戶端提供的所有輸入(例如,通常設置協議層消息的允許大小的上限)。當完整性檢查表明協議已被違反時,您將停止處理錯誤的消息。您可能還想記錄錯誤,並/或將其報告給客戶端。

如果違反協議會導致無法重新同步,那麼您別無選擇,只能斷開客戶端連接。這可以;行爲不端的客戶無權期待任何服務水平。

您可以設計允許再同步的協議 - 最簡單的例子是在後續協議消息之間的邊界處使用分隔符(分隔符本身不允許在消息中出現)。許多舊的「基於行」的互聯網協議,如FTP,SMTP和IRC以這種方式工作(本例中的分隔符是換行符)。

0

你可能想了解the protobuf-c RPC implementation

客戶端發出一個12字節的頭,在protobuf的編碼信息的有效載荷:

  • 方法指數(編碼爲4個字節的小 - 端點編號)
  • 消息長度:protobuf編碼有效負載的長度(編碼的4字節小端編號)
  • 請求標識:客戶端選擇的一個值,以允許它在多個未完成的請求的情況下知道哪個服務器響應對應於哪個請求)。 (在4個字節編碼)

服務器最終發出一個類似的16字節的響應:

  • 狀態代碼(如4個字節的小端數)。下列值的:
    0:成功
    1:服務失敗(即在NULL傳遞該消息到閉合)
    2:太多未決(客戶端連接有太多的未決請求)
  • 方法指數(相同請求)
  • 消息長度(相同請求)
  • 請求ID(相同請求)

另一件事到t如果你想通過非TCP/IP來做到這一點(即無錯通道)是在頭部和有效載荷上添加CRC校驗。

+0

好的,如果有人在傳輸中插入幾個破碎的字節,我應該怎麼做。例如,在「方法索引」和「消息長度」之間 – dipyalov

+0

除非你打算進行比CRC校驗更奇妙的事情(例如[錯誤檢測和校正編碼](http://en.wikipedia.org/wiki/) Error_detection_and_correction)),那麼我不知道如何檢測插入的字節不是預期的消息索引或消息長度。 –

1

這裏有兩個單獨的問題。

  1. 你如何處理協議 違規?
  2. 你打算如何計劃 保護你的服務器?

您無法通過在您的協議處理程序中構建錯誤糾正來保護您的服務器。你需要安全的編碼做法。仔細研究一下初學者的SSL - 如果你試圖讓服務器全部安全,那麼a)它不會,並且b)它需要很長時間。

您可能會發現,一旦服務器是安全的,協議錯誤的問題就更容易解決。這意味着客戶端的編碼錯誤或網絡數據完整性問題。預先排除惡意行爲會使問題更易於解決。

0

斷開行爲不當的客戶端

+0

問題是要檢測不正常行爲和正常傳輸開始的地方。 – dipyalov

+0

我覺得-1這個有點苛刻。我會這麼說,只要檢測到任何協議錯誤就立即斷開連接。不要嘗試和重新同步,不要嘗試和糾正錯誤,只要斷開即可。因此,假設您可以知道您何時收到無效數據,請斷開違規客戶端。 –

+0

這不是我:)但問題仍然存在 - 如何檢測missbehaviour和它發生的地方?我應該這樣做嗎? – dipyalov