1
0
Fork 0
scramble/main.go

153 lines
3.1 KiB
Go
Raw Normal View History

2018-02-14 21:54:18 +08:00
package main
import (
"flag"
2020-06-18 00:46:58 +08:00
"fmt"
2018-02-14 21:54:18 +08:00
"io"
"log"
"net"
2020-06-18 00:46:58 +08:00
"github.com/armon/go-socks5"
2018-02-14 21:54:18 +08:00
)
2020-06-18 00:46:58 +08:00
var keyInt int
2018-02-14 21:54:18 +08:00
var listen string
var connect string
func main() {
2020-06-18 00:46:58 +08:00
flag.IntVar(&keyInt, "key", 170, "key to xor the data")
flag.StringVar(&listen, "listen", ":8081", "listen on IP and port")
flag.StringVar(&connect, "connect", "socks", "forward to IP and port. 'socks' sets up a SOCKS5 proxy.")
2018-02-14 21:54:18 +08:00
flag.Parse()
2020-06-18 00:46:58 +08:00
if keyInt < 0 || keyInt > 255 {
2018-03-01 20:21:05 +08:00
flag.PrintDefaults()
2020-06-18 00:46:58 +08:00
log.Fatal(fmt.Errorf("key is not one byte"))
}
key := byte(keyInt)
var socks *socks5.Server
if connect == "socks" {
conf := &socks5.Config{}
var err error
socks, err = socks5.New(conf)
if err != nil {
log.Fatal(fmt.Errorf("unable to create socks server: %w", err))
}
2018-02-14 21:54:18 +08:00
}
2018-03-01 20:21:05 +08:00
// check and parse address
2020-06-18 00:46:58 +08:00
connAddr, err := net.ResolveTCPAddr("tcp", connect)
if socks == nil && err != nil {
2018-03-01 20:21:05 +08:00
flag.PrintDefaults()
2020-06-18 00:46:58 +08:00
log.Fatal(fmt.Errorf("invalid connect address %s: %w", connect, err))
2018-03-01 20:21:05 +08:00
}
2018-02-14 21:54:18 +08:00
2018-03-01 20:21:05 +08:00
// listen on address
2018-02-14 21:54:18 +08:00
ln, err := net.Listen("tcp", listen)
if err != nil {
flag.PrintDefaults()
2020-06-18 00:46:58 +08:00
log.Fatal(fmt.Errorf("unable to listen on %s: %w", listen, err))
2018-02-14 21:54:18 +08:00
}
2020-06-18 00:46:58 +08:00
for {
2018-02-14 21:54:18 +08:00
c, err := ln.Accept()
if err != nil {
2020-06-18 00:46:58 +08:00
log.Fatal(fmt.Errorf("unable to accept connection: %w", err))
2018-03-01 20:21:05 +08:00
}
2020-06-18 00:46:58 +08:00
log.Printf("connection from %v", c.RemoteAddr())
scrambleConn := NewScrambleConn(c, key)
if socks != nil {
go socks.ServeConn(scrambleConn)
} else {
conn, err := net.DialTCP("tcp", nil, connAddr)
if err != nil {
c.Close()
log.Print(fmt.Errorf("unable to connect to %v: %w", connAddr, err))
continue
}
2018-02-14 21:54:18 +08:00
2020-06-18 00:46:58 +08:00
result := Pipe(conn, scrambleConn)
go func() {
pipeResult := <-result
log.Printf("in: %d %v", pipeResult.Ingress.N, pipeResult.Ingress.Error)
log.Printf("eg: %d %v", pipeResult.Egress.N, pipeResult.Egress.Error)
}()
2018-02-14 21:54:18 +08:00
}
2018-03-01 20:21:05 +08:00
}
2020-06-18 00:46:58 +08:00
log.Printf("listening on %v", ln.Addr())
}
2018-03-01 20:21:05 +08:00
2020-06-18 00:46:58 +08:00
type CloseIndividual interface {
CloseRead() error
CloseWrite() error
}
2018-03-01 20:21:05 +08:00
2020-06-18 00:46:58 +08:00
type PipeResult struct {
Ingress CopyResult
Egress CopyResult
2018-02-14 21:54:18 +08:00
}
2020-06-18 00:46:58 +08:00
func Pipe(a, b io.ReadWriteCloser) chan PipeResult {
// Copy from b to a
ingressResult := Copy(a, b)
// Copy from a to b
egressResult := Copy(b, a)
result := make(chan PipeResult)
go func() {
var in CopyResult
var eg CopyResult
select {
case in = <-ingressResult:
// b returned error
// TODO: Consider error handling
closeOneSide(a, b)
eg = <-egressResult
case eg = <-egressResult:
// a returned error
// TODO: Consider error handling
closeOneSide(b, a)
in = <-ingressResult
2018-02-14 21:54:18 +08:00
}
2020-06-18 00:46:58 +08:00
result <- PipeResult{
Ingress: in,
Egress: eg,
2018-02-14 21:54:18 +08:00
}
2020-06-18 00:46:58 +08:00
}()
return result
}
func closeOneSide(a, b io.ReadWriteCloser) (aErr error, bErr error) {
if c, ok := a.(CloseIndividual); ok {
aErr = c.CloseWrite()
} else {
aErr = a.Close()
}
if c, ok := b.(CloseIndividual); ok {
bErr = c.CloseRead()
} else {
bErr = b.Close()
2018-02-14 21:54:18 +08:00
}
2020-06-18 00:46:58 +08:00
return
}
type CopyResult struct {
N int64
Error error
}
func Copy(w io.Writer, r io.Reader) chan CopyResult {
result := make(chan CopyResult)
go func() {
// Do a copy
n, err := io.Copy(w, r)
result <- CopyResult{n, err}
}()
return result
2018-02-14 21:54:18 +08:00
}