157 lines
4.1 KiB
Go
157 lines
4.1 KiB
Go
package main
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"flag"
|
|
"fmt"
|
|
"github.com/hashicorp/yamux"
|
|
"github.com/sirupsen/logrus"
|
|
"io"
|
|
Ligolo "ligolo"
|
|
"net"
|
|
)
|
|
|
|
func main() {
|
|
localServer := flag.String("p", "127.0.0.1:1080", "The local socks5 server address or ip:port to connect")
|
|
relayServer := flag.String("l", "0.0.0.0:443", "The relay server listening address (the connect-back address)")
|
|
certFile := flag.String("cert", "cert.pem", "The TLS server certificate,Unnecessary")
|
|
keyFile := flag.String("key", "key.pem", "The TLS server key,Unnecessary")
|
|
|
|
flag.Parse()
|
|
|
|
relay := NewLigoloRelay(*localServer, *relayServer, *certFile, *keyFile)
|
|
relay.Start()
|
|
}
|
|
|
|
// LigoloRelay structure contains configuration, the current session and the ConnectionPool
|
|
type LigoloRelay struct {
|
|
LocalServer string
|
|
RelayServer string
|
|
CertFile string
|
|
KeyFile string
|
|
ConnectionPool chan *yamux.Session
|
|
Session *yamux.Session
|
|
}
|
|
|
|
// NewLigoloRelay creates a new LigoloRelay struct
|
|
func NewLigoloRelay(localServer string, relayServer string, certFile string, keyFile string) *LigoloRelay {
|
|
return &LigoloRelay{LocalServer: localServer, RelayServer: relayServer, CertFile: certFile, KeyFile: keyFile, ConnectionPool: make(chan *yamux.Session, 100)}
|
|
}
|
|
|
|
// Start listening for local and relay connections
|
|
func (ligolo LigoloRelay) Start() {
|
|
|
|
logrus.WithFields(logrus.Fields{"socks5server": ligolo.LocalServer, "ligoloserver": ligolo.RelayServer}).Println("Ligolo server started.")
|
|
go ligolo.startRelayHandler()
|
|
ligolo.startLocalHandler()
|
|
}
|
|
|
|
// Listen for Ligolo connections
|
|
func (ligolo LigoloRelay) startRelayHandler() {
|
|
|
|
cer, err := tls.LoadX509KeyPair(ligolo.CertFile, ligolo.KeyFile)
|
|
if err != nil {
|
|
cer, _ = tls.X509KeyPair([]byte(Ligolo.CertPEM), []byte(Ligolo.KeyPEM))
|
|
//
|
|
//logrus.Warning("Could not load TLS certificate.")
|
|
//return
|
|
}
|
|
|
|
config := &tls.Config{Certificates: []tls.Certificate{cer}}
|
|
listener, err := tls.Listen("tcp4", ligolo.RelayServer, config)
|
|
if err != nil {
|
|
logrus.Errorf("Could not bind to port : %v\n", err)
|
|
return
|
|
}
|
|
defer listener.Close()
|
|
for {
|
|
c, err := listener.Accept()
|
|
if err != nil {
|
|
logrus.Errorf("Could not accept connection : %v\n", err)
|
|
return
|
|
}
|
|
|
|
session, err := handleRelayConnection(c)
|
|
if err != nil {
|
|
logrus.Errorf("Could not start session : %v\n", err)
|
|
continue
|
|
}
|
|
ligolo.ConnectionPool <- session
|
|
}
|
|
|
|
}
|
|
|
|
// Listen for local connections
|
|
func (ligolo LigoloRelay) startLocalHandler() {
|
|
listener, err := net.Listen("tcp4", ligolo.LocalServer)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return
|
|
}
|
|
defer listener.Close()
|
|
ligolo.Session = <-ligolo.ConnectionPool
|
|
go func() {
|
|
for {
|
|
<-ligolo.Session.CloseChan()
|
|
logrus.WithFields(logrus.Fields{"remoteaddr": ligolo.Session.RemoteAddr()}).Println("Received session shutdown.")
|
|
ligolo.Session = <-ligolo.ConnectionPool
|
|
logrus.WithFields(logrus.Fields{"remoteaddr": ligolo.Session.RemoteAddr()}).Println("New session acquired.")
|
|
}
|
|
}()
|
|
logrus.Println("Session acquired. Starting relay.")
|
|
for {
|
|
conn, err := listener.Accept()
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return
|
|
}
|
|
|
|
go ligolo.handleLocalConnection(conn)
|
|
}
|
|
}
|
|
|
|
// Handle new local connections
|
|
func (ligolo LigoloRelay) handleLocalConnection(conn net.Conn) {
|
|
if ligolo.Session.IsClosed() {
|
|
logrus.Warning("Closing connection because no session available !")
|
|
conn.Close()
|
|
return
|
|
}
|
|
|
|
logrus.Println("New proxy connection. Establishing new session.")
|
|
|
|
stream, err := ligolo.Session.Open()
|
|
if err != nil {
|
|
logrus.Errorf("Could not open session : %s\n", err)
|
|
return
|
|
}
|
|
|
|
logrus.Println("Yamux session established.")
|
|
|
|
go relay(conn, stream)
|
|
go relay(stream, conn)
|
|
|
|
}
|
|
|
|
// Handle new ligoloc connections
|
|
func handleRelayConnection(conn net.Conn) (*yamux.Session, error) {
|
|
logrus.WithFields(logrus.Fields{"remoteaddr": conn.RemoteAddr().String()}).Info("New relay connection.\n")
|
|
session, err := yamux.Server(conn, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
ping, err := session.Ping()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
logrus.Printf("Session ping : %v\n", ping)
|
|
return session, nil
|
|
}
|
|
|
|
func relay(src net.Conn, dst net.Conn) {
|
|
io.Copy(dst, src)
|
|
dst.Close()
|
|
src.Close()
|
|
return
|
|
}
|