mirror of
https://github.com/p4gefau1t/trojan-go.git
synced 2026-10-19 16:15:38 +00:00
add docker nightly image building actions
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'dev'
|
||||
pull_request:
|
||||
branches:
|
||||
- 'dev'
|
||||
name: docker-dev-build
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout the code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Dockerhub login
|
||||
env:
|
||||
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
||||
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
||||
run: |
|
||||
echo "${DOCKER_PASSWORD}" | docker login --username ${DOCKER_USERNAME} --password-stdin
|
||||
|
||||
- name: Prepare
|
||||
id: prepare
|
||||
run: |
|
||||
if [[ $GITHUB_REF == refs/tags/* ]]; then
|
||||
echo ::set-output name=version::${GITHUB_REF#refs/tags/}
|
||||
else
|
||||
echo ::set-output name=version::snapshot
|
||||
fi
|
||||
echo ::set-output name=docker_platforms::linux/arm/v7,linux/amd64
|
||||
echo ::set-output name=docker_image::${{ secrets.DOCKER_USERNAME }}/trojan-go
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: crazy-max/ghaction-docker-buildx@v1
|
||||
with:
|
||||
buildx-version: latest
|
||||
qemu-version: latest
|
||||
|
||||
- name: Build and push docker image
|
||||
run: |
|
||||
docker buildx build --platform ${{ steps.prepare.outputs.docker_platforms }} \
|
||||
--output "type=image,push=true" \
|
||||
--tag "${{ steps.prepare.outputs.docker_image }}:nightly" \
|
||||
--file Dockerfile .
|
||||
|
||||
test:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Test docker image
|
||||
run: |
|
||||
docker run --rm --entrypoint /usr/local/bin/trojan-go ${{ secrets.DOCKER_USERNAME }}/trojan-go -version
|
||||
-149
@@ -1,11 +1,9 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"net"
|
||||
|
||||
"github.com/golang/snappy"
|
||||
"github.com/p4gefau1t/trojan-go/log"
|
||||
)
|
||||
|
||||
@@ -142,150 +140,3 @@ func NewRewindConn(conn net.Conn) *RewindConn {
|
||||
R: NewRewindReader(conn),
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
compressionThreshold = 512
|
||||
)
|
||||
|
||||
type compFrame struct {
|
||||
Algorithm byte
|
||||
CompressedSize int
|
||||
Compressed []byte
|
||||
|
||||
OriginalSize int
|
||||
Original []byte
|
||||
}
|
||||
|
||||
func (h *compFrame) ReadFrom(r io.Reader) (int64, error) {
|
||||
buf := [3]byte{}
|
||||
n, err := r.Read(buf[:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if n != 3 {
|
||||
return 0, NewError("Too short")
|
||||
}
|
||||
h.Algorithm = buf[0]
|
||||
if h.Algorithm == 0 {
|
||||
h.OriginalSize = int(binary.LittleEndian.Uint16(buf[1:]))
|
||||
h.Original = make([]byte, h.OriginalSize)
|
||||
n, err := r.Read(h.Original)
|
||||
return int64(n), err
|
||||
}
|
||||
h.CompressedSize = int(binary.LittleEndian.Uint16(buf[1:]))
|
||||
h.Compressed = make([]byte, h.CompressedSize)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
n, err = r.Read(h.Compressed)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if n != h.CompressedSize {
|
||||
return 0, NewError("Too short")
|
||||
}
|
||||
h.Original, err = snappy.Decode(nil, h.Compressed)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
h.OriginalSize = len(h.Original)
|
||||
log.Trace("Compression ratio", float32(h.CompressedSize)/float32(h.OriginalSize))
|
||||
return int64(h.OriginalSize), nil
|
||||
}
|
||||
|
||||
func (h *compFrame) WriteTo(w io.Writer) (int64, error) {
|
||||
h.OriginalSize = len(h.Original)
|
||||
buf := [3]byte{}
|
||||
if h.OriginalSize < compressionThreshold {
|
||||
buf[0] = 0
|
||||
binary.LittleEndian.PutUint16(buf[1:], uint16(h.OriginalSize))
|
||||
n, err := w.Write(append(buf[:], h.Original...))
|
||||
n -= 3
|
||||
if n < 0 {
|
||||
n = 0
|
||||
}
|
||||
return int64(n), err
|
||||
}
|
||||
// TODO
|
||||
if h.CompressedSize > 0xffff {
|
||||
panic("todo")
|
||||
}
|
||||
buf[0] = 1
|
||||
h.Compressed = snappy.Encode(nil, h.Original)
|
||||
h.CompressedSize = len(h.Compressed)
|
||||
binary.LittleEndian.PutUint16(buf[1:], uint16(h.CompressedSize))
|
||||
n, err := w.Write(append(buf[:], h.Compressed...))
|
||||
n -= 3
|
||||
if n < 0 {
|
||||
n = 0
|
||||
}
|
||||
log.Trace("Compression ratio", float32(h.CompressedSize)/float32(h.OriginalSize))
|
||||
return int64(n), err
|
||||
}
|
||||
|
||||
type CompReader struct {
|
||||
rawReader io.Reader
|
||||
frame *compFrame
|
||||
readBytes int
|
||||
}
|
||||
|
||||
func (r *CompReader) readFrame(p []byte) (int, error) {
|
||||
n := copy(p, r.frame.Original[r.readBytes:])
|
||||
r.readBytes += n
|
||||
if r.readBytes >= r.frame.OriginalSize {
|
||||
//buffer is bigger than the frame
|
||||
r.frame = nil
|
||||
r.readBytes = 0
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (r *CompReader) Read(p []byte) (int, error) {
|
||||
if r.frame != nil {
|
||||
return r.readFrame(p)
|
||||
}
|
||||
r.frame = new(compFrame)
|
||||
_, err := r.frame.ReadFrom(r.rawReader)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return r.readFrame(p)
|
||||
}
|
||||
|
||||
type CompWriter struct {
|
||||
rawWriter io.Writer
|
||||
}
|
||||
|
||||
func (w *CompWriter) Write(p []byte) (int, error) {
|
||||
frame := &compFrame{
|
||||
OriginalSize: len(p),
|
||||
Original: p,
|
||||
}
|
||||
_, err := frame.WriteTo(w.rawWriter)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
type CompReadWriteCloser struct {
|
||||
*CompReader
|
||||
*CompWriter
|
||||
rawRWC io.ReadWriteCloser
|
||||
}
|
||||
|
||||
func (rwc *CompReadWriteCloser) Close() error {
|
||||
return rwc.rawRWC.Close()
|
||||
}
|
||||
|
||||
func NewCompReadWriteCloser(rwc io.ReadWriteCloser) (io.ReadWriteCloser, error) {
|
||||
return &CompReadWriteCloser{
|
||||
CompReader: &CompReader{
|
||||
rawReader: rwc,
|
||||
},
|
||||
CompWriter: &CompWriter{
|
||||
rawWriter: rwc,
|
||||
},
|
||||
rawRWC: rwc,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@ package common_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"github.com/p4gefau1t/trojan-go/common"
|
||||
@@ -36,27 +34,3 @@ func TestBufferedReader(t *testing.T) {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompressReadWriter(t *testing.T) {
|
||||
conn := bytes.NewBuffer(make([]byte, 0, 10000))
|
||||
//a, err := common.NewCompReadWriter(buf)
|
||||
type mockConn struct {
|
||||
io.ReadWriter
|
||||
io.Closer
|
||||
}
|
||||
a, err := common.NewCompReadWriteCloser(mockConn{
|
||||
ReadWriter: conn,
|
||||
Closer: ioutil.NopCloser(conn),
|
||||
})
|
||||
common.Must(err)
|
||||
payload := []byte{}
|
||||
for i := 0; i < 2048; i++ {
|
||||
payload = append(payload, 'A')
|
||||
}
|
||||
common.Must2(a.Write(payload))
|
||||
buf := make([]byte, 2048)
|
||||
common.Must2(a.Read(buf[:]))
|
||||
if !bytes.Equal(buf, payload) {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ type Address struct {
|
||||
NetworkType string
|
||||
net.IP
|
||||
AddressType
|
||||
Extensions []byte
|
||||
}
|
||||
|
||||
func (a *Address) String() string {
|
||||
|
||||
@@ -8,7 +8,6 @@ require (
|
||||
github.com/go-acme/lego/v3 v3.5.0
|
||||
github.com/go-sql-driver/mysql v1.5.0
|
||||
github.com/golang/protobuf v1.4.1
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
|
||||
github.com/mediocregopher/radix/v3 v3.5.0
|
||||
github.com/miekg/dns v1.1.29 // indirect
|
||||
|
||||
+7
-57
@@ -19,15 +19,7 @@ const (
|
||||
Connect Command = 1
|
||||
Bind Command = 2
|
||||
Associate Command = 3
|
||||
Extend Command = 0xff
|
||||
)
|
||||
|
||||
type Extension byte
|
||||
|
||||
const (
|
||||
Multiplexing Extension = 1
|
||||
Compression Extension = 2
|
||||
GarbageTraffic Extension = 3
|
||||
Mux Command = 0x7f
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -41,7 +33,6 @@ type Request struct {
|
||||
|
||||
Command
|
||||
*common.Address
|
||||
Extensions []Extension
|
||||
}
|
||||
|
||||
func (r *Request) Marshal(rr io.Reader) error {
|
||||
@@ -52,30 +43,12 @@ func (r *Request) Marshal(rr io.Reader) error {
|
||||
}
|
||||
r.Command = Command(byteBuf[0])
|
||||
switch r.Command {
|
||||
case Connect, Bind, Associate:
|
||||
case Connect, Bind, Associate, Mux:
|
||||
r.Address = new(common.Address)
|
||||
err := r.Address.Marshal(rr)
|
||||
if err != nil {
|
||||
return common.NewError("Failed to marshal address").Base(err)
|
||||
}
|
||||
case Extend:
|
||||
_, err := rr.Read(byteBuf[:])
|
||||
if err != nil {
|
||||
return common.NewError("Cannot read extensions count").Base(err)
|
||||
}
|
||||
extensionCount := byteBuf[0]
|
||||
if extensionCount == 0 || extensionCount > 32 {
|
||||
return common.NewError("Invalid extensions count").Base(err)
|
||||
}
|
||||
buf := [32]byte{}
|
||||
_, err = rr.Read(buf[:extensionCount])
|
||||
if err != nil {
|
||||
return common.NewError("Cannot read extensions").Base(err)
|
||||
}
|
||||
r.Extensions = make([]Extension, extensionCount)
|
||||
for i, e := range buf[:extensionCount] {
|
||||
r.Extensions[i] = Extension(e)
|
||||
}
|
||||
default:
|
||||
return common.NewError(fmt.Sprintf("Invalid command %d", r.Command))
|
||||
}
|
||||
@@ -85,19 +58,11 @@ func (r *Request) Marshal(rr io.Reader) error {
|
||||
func (r *Request) Unmarshal(w io.Writer) error {
|
||||
buf := bytes.NewBuffer(make([]byte, 0, 64))
|
||||
buf.WriteByte(byte(r.Command))
|
||||
switch r.Command {
|
||||
case Connect, Bind, Associate:
|
||||
if err := r.Address.Unmarshal(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
//use tcp by default
|
||||
r.Address.NetworkType = "tcp"
|
||||
case Extend:
|
||||
buf.WriteByte(byte(len(r.Extensions)))
|
||||
for _, e := range r.Extensions {
|
||||
buf.WriteByte(byte(e))
|
||||
}
|
||||
if err := r.Address.Unmarshal(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
//use tcp by default
|
||||
r.Address.NetworkType = "tcp"
|
||||
_, err := w.Write(buf.Bytes())
|
||||
return err
|
||||
}
|
||||
@@ -110,22 +75,7 @@ func (r *Request) Network() string {
|
||||
}
|
||||
|
||||
func (r *Request) String() string {
|
||||
if r.Address != nil {
|
||||
return r.Address.String()
|
||||
}
|
||||
return "REQUEST_WITH_EXTENSION"
|
||||
}
|
||||
|
||||
func (r *Request) ContainsExtension(e Extension) bool {
|
||||
if r.Extensions == nil {
|
||||
return false
|
||||
}
|
||||
for _, f := range r.Extensions {
|
||||
if f == e {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return r.Address.String()
|
||||
}
|
||||
|
||||
type HasHash interface {
|
||||
|
||||
@@ -30,7 +30,7 @@ func (m *SimpleSocksConnSession) Write(p []byte) (int, error) {
|
||||
}
|
||||
|
||||
func (m *SimpleSocksConnSession) Close() error {
|
||||
log.Info("simplesocks conn to", m.request, "closed", "sent:", common.HumanFriendlyTraffic(m.sent), "recv:", common.HumanFriendlyTraffic(m.recv))
|
||||
log.Info("Simplesocks conn to", m.request, "closed", "sent:", common.HumanFriendlyTraffic(m.sent), "recv:", common.HumanFriendlyTraffic(m.recv))
|
||||
return m.rwc.Close()
|
||||
}
|
||||
|
||||
|
||||
+5
-2
@@ -45,8 +45,11 @@ func (m *MuxManager) newMuxClient() (*muxClientInfo, error) {
|
||||
return nil, common.NewError("Duplicated id")
|
||||
}
|
||||
req := &protocol.Request{
|
||||
Command: protocol.Extend,
|
||||
Extensions: []protocol.Extension{protocol.Multiplexing},
|
||||
Command: protocol.Mux,
|
||||
Address: &common.Address{
|
||||
DomainName: "MUX_CONN",
|
||||
AddressType: common.DomainName,
|
||||
},
|
||||
}
|
||||
rwc, err := m.transport.DialToServer()
|
||||
if err != nil {
|
||||
|
||||
@@ -70,15 +70,7 @@ func (s *Server) handleConn(conn net.Conn) {
|
||||
}
|
||||
protocol.CancelTimeout(conn)
|
||||
|
||||
if req.ContainsExtension(protocol.Compression) {
|
||||
compConn, err := common.NewCompReadWriteCloser(inboundConn)
|
||||
if err != nil {
|
||||
log.Error(common.NewError("Failed to init compression layer").Base(err))
|
||||
}
|
||||
inboundConn = compConn
|
||||
}
|
||||
|
||||
if req.ContainsExtension(protocol.Multiplexing) {
|
||||
if req.Command == protocol.Mux {
|
||||
muxServer, err := smux.Server(inboundConn, nil)
|
||||
common.Must(err)
|
||||
defer muxServer.Close()
|
||||
|
||||
Reference in New Issue
Block a user