package module import ( "crypto/aes" "crypto/cipher" "crypto/md5" "crypto/rand" "io" "tunnel/pkg/server/env" "tunnel/pkg/server/opts" "tunnel/pkg/server/queue" ) type aesInfo struct { key []byte } type aesModule struct{} func (a *aesInfo) Send(rq, wq queue.Q) error { block, err := aes.NewCipher(a.key) if err != nil { return err } iv := make([]byte, aes.BlockSize) if _, err := rand.Read(iv); err != nil { return err } writer := &cipher.StreamWriter{ S: cipher.NewOFB(block, iv), W: wq.Writer(), } wq <- iv return queue.IoCopy(rq.Reader(), writer) } func (a *aesInfo) Recv(rq, wq queue.Q) error { block, err := aes.NewCipher(a.key) if err != nil { return err } r := rq.Reader() iv := make([]byte, aes.BlockSize) if _, err := io.ReadFull(r, iv); err != nil { if err == io.EOF { return nil } return err } reader := &cipher.StreamReader{ S: cipher.NewOFB(block, iv), R: r, } return queue.IoCopy(reader, wq.Writer()) } func newAes(env env.Env) *aesInfo { s := getAuthSecret(env) h := md5.Sum([]byte(s)) a := &aesInfo{key: make([]byte, 16)} copy(a.key, h[:]) return a } func (m aesModule) Open(env env.Env) (Pipe, Pipe) { a := newAes(env) return a.Send, a.Recv } func init() { register("aes", func(opts.Opts, env.Env) (module, error) { return aesModule{}, nil }) }