database64128 / shadowsocks-go

A versatile and efficient proxy platform for secure communications.
GNU Affero General Public License v3.0
136 stars 17 forks source link

Usage as a library #44

Open ice-dionysos opened 1 year ago

ice-dionysos commented 1 year ago

Discussion thread of #43

The use case as simple as possible: an ability to create and manager a single server without external HTTP API.


Server configuration example:

sc := ss.Config{
    Servers: []ss.ServerConfig{
        {
            Name:              "foo",
            Protocol:          "2022-blake3-aes-256-gcm",
            MTU:               1500,
            Listen:            ":43333",
            EnableTCP:         true,
            EnableUDP:         true,
            ListenerTFO:       true,
            UDPRelayBatchSize: 8,
            PSK:           "mypassword",
            UPSKStorePath: "/dev/zero",
        },
    },
}

Now we need an ability to add/remove/list users of that server via Manager.

database64128 commented 1 year ago

You probably want to use /dev/null as the uPSK store path.

Actually, you don't even need a ServerConfig. cred.Manager was written to manage the credential file, and you don't need that. All you need is access to ss2022.CredStore, which was embedded into ss2022.TCPServer and ss2022.UDPServer and can be accessed directly.

When you omit the need for multiple servers and clients and routing rules, the initialization process is actually not that complex, and should be easy to implement in your own code. You could do something like:

cc := ClientConfig{
    Name:      "direct",
    Protocol:  "direct",
    EnableTCP: true,
    DialerTFO: true,
    EnableUDP: true,
    MTU:       1500,
}

err := cc.Initialize(nil, nil, logger)
// error handling

tcpClient, err := cc.TCPClient()
// error handling

udpClient, err := cc.UDPClient()
// error handling

router, err := router.Config{}.Router(logger, nil, nil, map[string]zerocopy.TCPClient{"direct": tcpClient}, map[string]zerocopy.UDPClient{"direct": udpClient}, nil)
// error handling

// Then you copy the logic you need from service/server.go
ice-dionysos commented 1 year ago

I guess that will work, buy anyway, I would prefer not to touch internals and have some high-level API for all those initialization/creation things.

server := Config{}
server.Start(ctx)
...
server.UserAdd("foo", key)
server.UserRemove("foo")
...
server.Stop()
database64128 commented 1 year ago

What you are proposing might look nice at first glance, but it's going to create a lot of mess when you start implementing it. It's fundamentally incompatible with shadowsocks-go's architecture.

The relay services (service.TCPRelay, service.UDPNATRelay, service.UDPSessionRelay, service.UDPTransparentRelay) don't create, own, or care about which protocol server they are running. You just hand it a server, and start the service. So it would look really out of place when you add protocol-specific methods to relay services.