1. 程式人生 > 實用技巧 >想用Nginx代理一切?行!

想用Nginx代理一切?行!

Nginx能代理一切嗎?

是的,Nginx可以作為一個優秀的http閘道器,但nginx能代理SSH2,MySQL,Oracle的連線嗎?也算行吧,nginx有stream-module,專門處理TCP,UDP連線。不過即使忽略

  • stream-module反人類的使用方式、
  • nginx內部複雜的階段劃分、
  • 各個階段對使用方式的限制、
  • 以及為了完成某個功能不得不重新編譯下載的一系列缺點,

Stream-module的功能也遠遠不夠。不信你可以試試修改一個包的內容,或者自動回覆某種型別的包試試,更別提完成這樣幾個操作:修改一下客戶端輸入的sql語句,或者更進一步,加入一個身份驗證。

如果你是一個nginx+lua或Openresty或KONG或APISix的閘道器重度依賴使用者,那麼你肯定急切的希望把閘道器的能力擴充套件到TCP/IP領域。

我們來看幾個示例

修改Linux|Unix歡迎螢幕為所有男人的夢想

記錄SQL或shell命令


防止刪庫跑路(命令過濾和禁止)


踢人下線

怎麼做到的

上面的示例是怎麼做到的?不要著急,我們的主人公就要出場了:SuProxy,一個純Lua,事件驅動模型,基於包分析的開源代理庫。

純LUA意味著拷貝可用,事件驅動意味著使用方便,包分析意味著可以真正自由修改包內容

我們來看看怎麼修改linux的歡迎螢幕

local function myWelcome(context,source)
	local digger={"\r\n",
	[[                                                     .-.   ]].."\r\n",
	[[                                                    /   \  ]].."\r\n",
	[[                                     _____.....-----|(o) | ]].."\r\n",
	[[                               _..--'          _..--|  .'' ]].."\r\n",
	[[                             .'  o      _..--''     |  | | ]].."\r\n",
	[[                            /  _/_..--''            |  | | ]].."\r\n",
	[[                   ________/  / /                   |  | | ]].."\r\n",
	[[                  | _  ____\ / /                    |  | | ]].."\r\n",
	[[ _.-----._________|| ||    \\ /                     |  | | ]].."\r\n",
	[[|=================||=||_____\\                      |__|-' ]].."\r\n",
	[[|   suproxy       ||_||_____//                      (o\ |  ]].."\r\n",
	[[|_________________|_________/                        |-\|  ]].."\r\n",
	[[ `-------------._______.----'                        /  `. ]].."\r\n",
	[[    .,.,.,.,.,.,.,.,.,.,.,.,.,                      /     \]].."\r\n",
	[[   ((O) o o o o ======= o o(O))                 ._.'      /]].."\r\n",
	[[    `-.,.,.,.,.,.,.,.,.,.,.,-'                   `.......' ]].."\r\n",
	[[                   scan me to login                        ]].."\r\n",
	"\r\n",
	}                      
	return table.concat(digger),false
end

local ssh=require("suproxy.ssh2"):new()
local cmd=require("suproxy.ssh2.commandCollector"):new()
cmd.BeforeWelcomeEvent:addHandler(ssh,myWelcome)
local channel=require("suproxy.channel"):new({{ip="127.0.0.1",port=2222}},ssh)
channel:run()

上面的例子裡,通過處理commandCollector.BeforeWelcomeEvent事件,在事件中修改了預設的歡迎螢幕。

每個協議都有自己獨特的事件,比如利用TNSProcessor.commandEntered事件,我們就能過濾使用者輸入的命令,使用OnAuthenticate事件就能夠自行處理驗證。事件的使用可參見https://www.cnblogs.com/yizhu2000/p/13885263.html或英文文件https://github.com/yizhu2000/suproxy

還想更進一步

除了上面這些直觀的事件,在底層SuProxy還為高階使用者提供了協議解析事件,這些事件把協議內部的包往來暴露出來,使用者可以處理這些事件從而修改包的內容,實現更高階的邏輯,比如SSH2協議提供瞭如下事件(C2P意味著從Client到SuProxy,S2P意味著從SuProxy到Server)

C2PParser.events.KeyXInitEvent,C2PParser.events.AuthReqEvent,C2PParser.events.DHKeyXInitEvent,C2PParser.events.NewKeysEvent,C2PParser.events.ChannelDataEvent,S2PParser.events.KeyXInitEvent,S2PParser.events.DHKeyXReplyEvent,S2PParser.events.AuthSuccessEvent,S2PParser.events.AuthFailEvent,S2PParser.events.NewKeysEvent,S2PParser.events.ChannelDataEvent

熟悉SSH2協議的同學可以自行解析擴充套件。

實現方式

SuProxy自行處理了request socket的資料,並在上下游間建立通道,在通道中使用不同處理器處理協議相關的內容

Channel 負責管理連線,資料收發

Parser負責進行解析和打包

Processor 負責處理加解密及對解析後的包進行業務處理

其中processor和parser使用者都可以自行擴充套件,增加processor可以擴充套件協議,增加parser可以擴充套件協議中某類特定包的解析

三個層次都會發出事件。具體可見下圖

歡迎拍磚

看了上面的介紹,感興趣的同學有問題可以在此留言,或直接在git上提交
https://github.com/yizhu2000/suproxy/issues

也可以通過郵件組[email protected],或直接發郵件到[email protected]進行溝通

當然SuProxy當前還在試驗階段,已經支援SSH2,LDAP,TNS,TDS協議,使用示例和文件將會陸續在部落格園,CSDN部落格,Git上釋出,歡迎大家測試,並提出意見與建議,

專案Git地址:
https://github.com/yizhu2000/suproxy

文件地址(英文):
https://github.com/yizhu2000/suproxy/blob/main/readme.md