My awesome intercepting, load balancing and session management libraries for nginx+lua
Tags: lua, nginx, ssh2, tns
Published: 2020-10-28 08:10:33

I'm working on an awesome event-driven Lua proxy libraries for analyzing, intercepting, load balancing and session management.  

source and doc address on github
https://github.com/yizhu2000/suproxy

It provides APIs for:

- Authentication intercept: Read or change credentials during authentication or introduce self-defined authenticator.
- Command Input Intercept: monitor, filter or change command input.
- Command Output Intercept: monitor, filter or change command reply.
- Context Collect: Get network, user, client and server information like IP, port, version etc.
- Session Manage: Store session in Redis, provide APIs for list, kill and search session.
- Protocol parser: Parse and encode protocol packets.
- Load Balance: Multi-upstream balancing with fault tolerance.

Here are some screenshort for：
Filter SQL for Oracle
![](https://dev-to-uploads.s3.amazonaws.com/i/g6auhmjdz1zt31gq1436.png)
Filter Command for linux/Unix
![](https://dev-to-uploads.s3.amazonaws.com/i/rit3udhr5n819lijimfz.png)
Log operation for SSH2
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/zcattp29jq8k22i8rnf4.png)
Log operation for SQL
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/p7me92y0kxfv4vq64000.png)
Change welcome info for linux/Unix 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/11bkfpim22yftrevsoux.png)
Currently, supported protocols include SSH2, ORACLE TNS, SQLSERVER TDS, LDAP.

|                                                              | SSH   | SQL Server | Oracle | LDAP  |
| ------------------------------------------------------------ | ----- | ---------- | ------ | ----- |
| Get Username                                                 | Y[^1] | Y[^2]      | Y      | Y[^6] |
| Get Password                                                 | Y[^1] | Y[^2]      | N      | Y[^6] |
| Change Username                                              | Y     | Y          | Y[^4]  | Y     |
| Change Password                                              | Y     | Y          | N      | Y     |
| Third-Party Auth                                             | Y     | Y          | Y[^5]  | Y     |
| Get Command                                                  | Y     | Y          | Y      | Y[^7] |
| Get Reply                                                    | Y     | Y          | N      | Y[^7] |
| Change Command                                               | Y     | Y[^3]      | Y[^3]  | N     |
| Get Network Context<br />(IP,port etc).                      | Y     | Y          | Y      | Y     |
| Get Client Context<br />(client/server program name <br />and version etc.) | Y     | Y          | Y      | N     |

- [^1]: Password authentication only

- [^2]: Get username and password for SQL server disables SSL encryption

- [^3]: Change SQL command is not fully tested, some change like change select command to delete command may not success

- [^4]: Change Username for oracle10 is not supported

- [^5]: Only username based authentication supported

- [^6]: SSL not supported

- [^7]: Only search request and it's reply supported


SuProxy is written by pure Lua , and is designed under event-driven pattern, the use and extension of SuProxy libraries are simple: start a listener channel and handle it's event. This example shows how to start a SSH2 listener and handle authenticate success event of SSH connection. 

```lua
server {
    listen 22;
    content_by_lua_block {
        local ssh=require("suproxy.ssh2"):new()
        local channel=require("suproxy.channel"):new({{ip="192.168.1.135",port=22}},tds)
        channel:run()
		ssh.AuthSuccessEvent:addHandler(ssh,logAuth)
    }
}
```

SuProxy provides basic load balancing ability.  The example below shows how to pass multiple upstream to channel.

```lua
package.loaded.my_SSHB=package.loaded.my_SSHB or
require ("suproxy.balancer.balancer"):new{
    {ip="127.0.0.1",port=2222,id="local",gid="linuxServer"},
    {ip="192.168.46.128",port=22,id="remote",gid="linuxServer"},
    {ip="192.168.1.121",port=22,id="UBUNTU14",gid="testServer"}
}
local channel=require("suproxy.channel"):new(package.loaded.my_SSHB,ssh)
```

SuProxy can collect and maintain session context in memory or redis , below are the information collected by SuProxy in ssh connection. 

```json
{
	"sid": "xxxxxxxxxxxx",
	"uid": "xxxx",
	"stype": "ssh2",
	"uptime": 1600831353.066,
	"ctime": 1600831353.066,
	"ctx": {
		"srvIP": "127.0.0.1",
		"client": "SSH-2.0-PuTTY_Release_0.74",
		"clientIP": "127.0.0.1",
		"clientPort": "56127",
        "username": "xxxx",
		"srvPort": 2222,
		"server": "SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.1"
	}
}
```

#