Skip to content

qdm12/ss-server

Repository files navigation

Shadowsocks server

Focuses on a Dockerized Shadowsocks server as well as giving an easy to use Go API to run a Shadowsocks server.

❓ Question, suggestion, request? ➡️ Create an issue!

Build status

dockeri.co

Last release Last Docker tag Last release size GitHub last release date Commits since release

Latest size

GitHub last commit GitHub commit activity GitHub closed PRs GitHub issues GitHub closed issues

Lines of code Code size GitHub repo size Go version

MIT Visitors count

Docker

The Docker image is:

  • Based on Scratch (no OS) for a total size of 6MB
  • Compatible with all the CPU architectures supported by Docker: linux/amd64, linux/386, linux/arm64, linux/arm/v6, linux/arm/v7, linux/s390x, linux/ppc64le and linux/riscv64
  • Shadowsocks is implemented in Go and compiled statically using Go 1.22

Run the container interactively to try it out

docker run -it --rm -p 8388:8388/tcp -p 8388:8388/udp -e PASSWORD=password qmcgaw/ss-server

Or use docker-compose.yml with docker-compose up -d

version: "3.7"
services:
  shadowsocks:
      image: qmcgaw/ss-server
      container_name: shadowsocks
      network_mode: bridge
      ports:
          - 8388:8388/tcp
          - 8388:8388/udp
      environment:
          - PASSWORD=password
          - TZ=
      restart: always

The environment variables are:

Name Default Possible values Description
PASSWORD Any password Your password
LISTENING_ADDRESS :8388 Listening address Internal listening address
LOG_LEVEL INFO INFO, ERROR, DEBUG Log level
CIPHER chacha20-ietf-poly1305 chacha20-ietf-poly1305, aes-128-gcm, aes-256-gcm Cipher to use
TZ Timezone, i.e. America/Montreal Timezone for log times display
PROFILING off on or off Enable the Go pprof http server on :6060

Go API

This repository was designed such that it is easy to integrate and launch safely a Shadowsocks server from an existing Go program.

TCP+UDP example

Source file

package main

import (
    "context"
    "fmt"
    "os"

    "github.com/qdm12/ss-server/pkg/tcpudp"
)

func main() {
    logger := &logger{}
    password := "password"
    address := ":8388"
    settings := tcpudp.Settings{
        Address:    &address,
        CipherName: "aes-256-gcm",
        Password:   &password,
    }
    server, err := tcpudp.NewServer(settings, logger)
    if err != nil {
        logger.Error(err.Error())
        os.Exit(1)
    }
    ctx := context.Background()
    err = server.Listen(ctx) // blocking call, can be run in a goroutine
    if err != nil {
        logger.Error(err.Error())
    }
}

type logger struct{}

func (l *logger) Debug(s string) { fmt.Println("debug:", s) }
func (l *logger) Info(s string)  { fmt.Println("info:", s) }
func (l *logger) Error(s string) { fmt.Println("error:", s) }

The call to server.Listen(ctx, ":8388") is blocking but you can run in a goroutine and cancel the context ctx when you want to stop the server.

TCP only and UDP only

API for the TCP only and UDP only are almost the same, with the difference that they return an error on exit.

Docker entrypoint

Have also a look at the cmd/ss-server/main.go which is quite straight forward to understand but uses a bit more complex asynchronous parts.

On demand

  • SIP003 plugins

TODOS

  • Support hex raw keys instead of passwords
  • Prometheus stats
  • Docker healthcheck + healthcheck endpoint (i.e. for K8s)

About

Shadowsocks server to use with Docker and to integrate in other Go programs

Resources

License

Stars

Watchers

Forks

Sponsor this project