add forward support
This commit is contained in:
parent
9b2bd7a88c
commit
1c76ca4b26
@ -38,13 +38,16 @@ func (c *Chain) LastNode() Node {
|
|||||||
|
|
||||||
// AddNode appends the node(s) to the chain.
|
// AddNode appends the node(s) to the chain.
|
||||||
func (c *Chain) AddNode(nodes ...Node) {
|
func (c *Chain) AddNode(nodes ...Node) {
|
||||||
|
if c == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
c.nodes = append(c.nodes, nodes...)
|
c.nodes = append(c.nodes, nodes...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsEmpty checks if the chain is empty.
|
// IsEmpty checks if the chain is empty.
|
||||||
// An empty chain means that there is no proxy node in the chain.
|
// An empty chain means that there is no proxy node in the chain.
|
||||||
func (c *Chain) IsEmpty() bool {
|
func (c *Chain) IsEmpty() bool {
|
||||||
return len(c.nodes) == 0
|
return c == nil || len(c.nodes) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dial connects to the target address addr through the chain.
|
// Dial connects to the target address addr through the chain.
|
||||||
|
@ -26,14 +26,12 @@ func (c *Client) Dial(addr string) (net.Conn, error) {
|
|||||||
return c.Transporter.Dial(addr)
|
return c.Transporter.Dial(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handshake performs a handshake with the proxy.
|
// Handshake performs a handshake with the proxy over connection conn.
|
||||||
// The conn should be an connection to this proxy.
|
|
||||||
func (c *Client) Handshake(conn net.Conn) (net.Conn, error) {
|
func (c *Client) Handshake(conn net.Conn) (net.Conn, error) {
|
||||||
return c.Transporter.Handshake(conn)
|
return c.Transporter.Handshake(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect connects to the address addr via the proxy.
|
// Connect connects to the address addr via the proxy over connection conn.
|
||||||
// The conn should be an connection to this proxy.
|
|
||||||
func (c *Client) Connect(conn net.Conn, addr string) (net.Conn, error) {
|
func (c *Client) Connect(conn net.Conn, addr string) (net.Conn, error) {
|
||||||
return c.Connector.Connect(conn, addr)
|
return c.Connector.Connect(conn, addr)
|
||||||
}
|
}
|
||||||
|
419
gost/forward.go
Normal file
419
gost/forward.go
Normal file
@ -0,0 +1,419 @@
|
|||||||
|
package gost
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"errors"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/ginuerzh/gosocks5"
|
||||||
|
"github.com/go-log/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type tcpForwardHandler struct {
|
||||||
|
raddr string
|
||||||
|
options *HandlerOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// TCPForwardHandler creates a server Handler for TCP port forwarding server.
|
||||||
|
// The raddr is the remote address that the server will forward to.
|
||||||
|
func TCPForwardHandler(raddr string, opts ...HandlerOption) Handler {
|
||||||
|
h := &tcpForwardHandler{
|
||||||
|
raddr: raddr,
|
||||||
|
options: &HandlerOptions{
|
||||||
|
Chain: new(Chain),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(h.options)
|
||||||
|
}
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *tcpForwardHandler) Handle(conn net.Conn) {
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
log.Logf("[tcp] %s - %s", conn.RemoteAddr(), h.raddr)
|
||||||
|
cc, err := h.options.Chain.Dial(h.raddr)
|
||||||
|
if err != nil {
|
||||||
|
log.Logf("[tcp] %s -> %s : %s", conn.RemoteAddr(), h.raddr, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer cc.Close()
|
||||||
|
|
||||||
|
log.Logf("[tcp] %s <-> %s", conn.RemoteAddr(), h.raddr)
|
||||||
|
transport(conn, cc)
|
||||||
|
log.Logf("[tcp] %s >-< %s", conn.RemoteAddr(), h.raddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
type udpForwardHandler struct {
|
||||||
|
raddr string
|
||||||
|
ttl time.Duration
|
||||||
|
options *HandlerOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// UDPForwardHandler creates a server Handler for UDP port forwarding server.
|
||||||
|
// The raddr is the remote address that the server will forward to.
|
||||||
|
func UDPForwardHandler(raddr string, ttl time.Duration, opts ...HandlerOption) Handler {
|
||||||
|
h := &udpForwardHandler{
|
||||||
|
raddr: raddr,
|
||||||
|
ttl: ttl,
|
||||||
|
options: &HandlerOptions{
|
||||||
|
Chain: new(Chain),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(h.options)
|
||||||
|
}
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *udpForwardHandler) Handle(conn net.Conn) {
|
||||||
|
defer conn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
type rtcpForwardHandler struct {
|
||||||
|
laddr string
|
||||||
|
raddr string
|
||||||
|
options *HandlerOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// RTCPForwardHandler creates a server Handler for TCP remote port forwarding server.
|
||||||
|
// The raddr is the remote address that the server will forward to.
|
||||||
|
func RTCPForwardHandler(laddr, raddr string, opts ...HandlerOption) Handler {
|
||||||
|
h := &rtcpForwardHandler{
|
||||||
|
laddr: laddr,
|
||||||
|
raddr: raddr,
|
||||||
|
options: &HandlerOptions{},
|
||||||
|
}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(h.options)
|
||||||
|
}
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *rtcpForwardHandler) Handle(conn net.Conn) {
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
cc, err := net.DialTimeout("tcp", h.raddr, DialTimeout)
|
||||||
|
if err != nil {
|
||||||
|
log.Logf("[rtcp] %s -> %s : %s", h.laddr, h.raddr, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer cc.Close()
|
||||||
|
|
||||||
|
log.Logf("[rtcp] %s <-> %s", h.laddr, h.raddr)
|
||||||
|
transport(cc, conn)
|
||||||
|
log.Logf("[rtcp] %s >-< %s", h.laddr, h.raddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
type rudpForwardHandler struct {
|
||||||
|
laddr string
|
||||||
|
raddr string
|
||||||
|
options *HandlerOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// RUDPForwardHandler creates a server Handler for UDP remote port forwarding server.
|
||||||
|
// The raddr is the remote address that the server will forward to.
|
||||||
|
func RUDPForwardHandler(laddr, raddr string, opts ...HandlerOption) Handler {
|
||||||
|
h := &rudpForwardHandler{
|
||||||
|
laddr: laddr,
|
||||||
|
raddr: raddr,
|
||||||
|
options: &HandlerOptions{},
|
||||||
|
}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(h.options)
|
||||||
|
}
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *rudpForwardHandler) Handle(conn net.Conn) {
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
// TODO: handle connection
|
||||||
|
|
||||||
|
/*
|
||||||
|
ra, err := net.ResolveUDPAddr("udp", h.raddr)
|
||||||
|
if err != nil {
|
||||||
|
log.Logf("[rudp] %s - %s : %s", h.laddr, h.raddr, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
dgram, err := gosocks5.ReadUDPDatagram(conn)
|
||||||
|
if err != nil {
|
||||||
|
log.Logf("[rudp] %s -> %s : %s", h.laddr, h.raddr, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
b := make([]byte, mediumBufferSize)
|
||||||
|
|
||||||
|
relay, err := net.DialUDP("udp", nil, ra)
|
||||||
|
if err != nil {
|
||||||
|
log.Logf("[rudp] %s -> %s : %s", h.laddr, h.raddr, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer relay.Close()
|
||||||
|
|
||||||
|
if _, err := relay.Write(dgram.Data); err != nil {
|
||||||
|
log.Logf("[rudp] %s -> %s : %s", h.laddr, h.raddr, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if Debug {
|
||||||
|
log.Logf("[rudp] %s >>> %s length: %d", h.laddr, h.raddr, len(dgram.Data))
|
||||||
|
}
|
||||||
|
relay.SetReadDeadline(time.Now().Add(ReadTimeout))
|
||||||
|
n, err := relay.Read(b)
|
||||||
|
if err != nil {
|
||||||
|
log.Logf("[rudp] %s <- %s : %s", h.laddr, h.raddr, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
relay.SetReadDeadline(time.Time{})
|
||||||
|
if Debug {
|
||||||
|
log.Logf("[rudp] %s <<< %s length: %d", h.laddr, h.raddr, n)
|
||||||
|
}
|
||||||
|
conn.SetWriteDeadline(time.Now().Add(WriteTimeout))
|
||||||
|
if err := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(uint16(n), 0, dgram.Header.Addr), b[:n]).Write(conn); err != nil {
|
||||||
|
log.Logf("[rudp] %s <- %s : %s", h.laddr, h.raddr, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
conn.SetWriteDeadline(time.Time{})
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
type udpForwardListener struct {
|
||||||
|
addr *net.UDPAddr
|
||||||
|
conn *net.UDPConn
|
||||||
|
}
|
||||||
|
|
||||||
|
// UDPForwardListener creates a Listener for UDP port forwarding server.
|
||||||
|
func UDPForwardListener(addr string) (Listener, error) {
|
||||||
|
laddr, err := net.ResolveUDPAddr("udp", addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
conn, err := net.ListenUDP("udp", laddr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &udpForwardListener{conn: conn}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *udpForwardListener) Accept() (net.Conn, error) {
|
||||||
|
// TODO: create udp forward connection
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *udpForwardListener) Addr() net.Addr {
|
||||||
|
return l.addr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *udpForwardListener) Close() error {
|
||||||
|
return l.conn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
type rtcpForwardListener struct {
|
||||||
|
addr net.Addr
|
||||||
|
chain *Chain
|
||||||
|
selector *clientSelector
|
||||||
|
close chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RTCPForwardListener creates a Listener for TCP remote port forwarding server.
|
||||||
|
func RTCPForwardListener(addr string, chain *Chain) (Listener, error) {
|
||||||
|
laddr, err := net.ResolveTCPAddr("tcp", addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if chain.IsEmpty() || chain.LastNode().Protocol != "socks5" {
|
||||||
|
return nil, errors.New("invalid chain")
|
||||||
|
}
|
||||||
|
selector := &clientSelector{
|
||||||
|
TLSConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
|
User: chain.LastNode().User,
|
||||||
|
}
|
||||||
|
selector.AddMethod(
|
||||||
|
gosocks5.MethodNoAuth,
|
||||||
|
gosocks5.MethodUserPass,
|
||||||
|
MethodTLS,
|
||||||
|
)
|
||||||
|
|
||||||
|
return &rtcpForwardListener{
|
||||||
|
addr: laddr,
|
||||||
|
chain: chain,
|
||||||
|
selector: selector,
|
||||||
|
close: make(chan struct{}),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *rtcpForwardListener) Accept() (net.Conn, error) {
|
||||||
|
select {
|
||||||
|
case <-l.close:
|
||||||
|
return nil, errors.New("closed")
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
if l.chain.IsEmpty() || l.chain.LastNode().Protocol != "socks5" {
|
||||||
|
return nil, errors.New("invalid chain")
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := l.chain.Conn()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
cc, err := l.handshake(conn)
|
||||||
|
if err != nil {
|
||||||
|
conn.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return cc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *rtcpForwardListener) handshake(conn net.Conn) (net.Conn, error) {
|
||||||
|
cc := gosocks5.ClientConn(conn, l.selector)
|
||||||
|
if err := cc.Handleshake(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
conn = cc
|
||||||
|
|
||||||
|
req := gosocks5.NewRequest(gosocks5.CmdBind, toSocksAddr(l.addr))
|
||||||
|
if err := req.Write(conn); err != nil {
|
||||||
|
log.Log("[rtcp] SOCKS5 BIND request: ", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// first reply, bind status
|
||||||
|
conn.SetReadDeadline(time.Now().Add(ReadTimeout))
|
||||||
|
rep, err := gosocks5.ReadReply(conn)
|
||||||
|
if err != nil {
|
||||||
|
log.Log("[rtcp] SOCKS5 BIND reply: ", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
conn.SetReadDeadline(time.Time{})
|
||||||
|
if rep.Rep != gosocks5.Succeeded {
|
||||||
|
log.Logf("[rtcp] bind on %s failure", l.addr)
|
||||||
|
return nil, fmt.Errorf("Bind on %s failure", l.addr.String())
|
||||||
|
}
|
||||||
|
log.Logf("[rtcp] BIND ON %s OK", rep.Addr)
|
||||||
|
|
||||||
|
// second reply, peer connected
|
||||||
|
rep, err = gosocks5.ReadReply(conn)
|
||||||
|
if err != nil {
|
||||||
|
log.Log("[rtcp]", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if rep.Rep != gosocks5.Succeeded {
|
||||||
|
log.Logf("[rtcp] peer connect failure: %d", rep.Rep)
|
||||||
|
return nil, errors.New("peer connect failure")
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Logf("[rtcp] PEER %s CONNECTED", rep.Addr)
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *rtcpForwardListener) Addr() net.Addr {
|
||||||
|
return l.addr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *rtcpForwardListener) Close() error {
|
||||||
|
close(l.close)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type rudpForwardListener struct {
|
||||||
|
addr net.Addr
|
||||||
|
chain *Chain
|
||||||
|
selector *clientSelector
|
||||||
|
close chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RUDPForwardListener creates a Listener for UDP remote port forwarding server.
|
||||||
|
func RUDPForwardListener(addr string, chain *Chain) (Listener, error) {
|
||||||
|
laddr, err := net.ResolveUDPAddr("udp", addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if chain.IsEmpty() || chain.LastNode().Protocol != "socks5" {
|
||||||
|
return nil, errors.New("invalid chain")
|
||||||
|
}
|
||||||
|
selector := &clientSelector{
|
||||||
|
TLSConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
|
User: chain.LastNode().User,
|
||||||
|
}
|
||||||
|
selector.AddMethod(
|
||||||
|
gosocks5.MethodNoAuth,
|
||||||
|
gosocks5.MethodUserPass,
|
||||||
|
MethodTLS,
|
||||||
|
)
|
||||||
|
|
||||||
|
return &rudpForwardListener{
|
||||||
|
addr: laddr,
|
||||||
|
chain: chain,
|
||||||
|
selector: selector,
|
||||||
|
close: make(chan struct{}),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *rudpForwardListener) Accept() (net.Conn, error) {
|
||||||
|
select {
|
||||||
|
case <-l.close:
|
||||||
|
return nil, errors.New("closed")
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := l.chain.Conn()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
cc, err := l.handshake(conn)
|
||||||
|
if err != nil {
|
||||||
|
conn.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
conn = cc
|
||||||
|
|
||||||
|
return cc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *rudpForwardListener) handshake(conn net.Conn) (net.Conn, error) {
|
||||||
|
cc := gosocks5.ClientConn(conn, l.selector)
|
||||||
|
if err := cc.Handleshake(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
conn = cc
|
||||||
|
|
||||||
|
req := gosocks5.NewRequest(CmdUDPTun, toSocksAddr(l.addr))
|
||||||
|
if err := req.Write(conn); err != nil {
|
||||||
|
log.Log("[rudp] SOCKS5 UDP relay request: ", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
conn.SetReadDeadline(time.Now().Add(ReadTimeout))
|
||||||
|
rep, err := gosocks5.ReadReply(conn)
|
||||||
|
if err != nil {
|
||||||
|
log.Log("[rudp] SOCKS5 UDP relay reply: ", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
conn.SetReadDeadline(time.Time{})
|
||||||
|
if rep.Rep != gosocks5.Succeeded {
|
||||||
|
log.Logf("[rudp] bind on %s failure: %d", l.addr, rep.Rep)
|
||||||
|
return nil, fmt.Errorf("Bind on %s failure", l.addr.String())
|
||||||
|
}
|
||||||
|
log.Logf("[rudp] BIND ON %s OK", rep.Addr)
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *rudpForwardListener) Addr() net.Addr {
|
||||||
|
return l.addr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *rudpForwardListener) Close() error {
|
||||||
|
close(l.close)
|
||||||
|
return nil
|
||||||
|
}
|
@ -25,9 +25,9 @@ var (
|
|||||||
// DialTimeout is the timeout of dial.
|
// DialTimeout is the timeout of dial.
|
||||||
DialTimeout = 30 * time.Second
|
DialTimeout = 30 * time.Second
|
||||||
// ReadTimeout is the timeout for reading.
|
// ReadTimeout is the timeout for reading.
|
||||||
ReadTimeout = 90 * time.Second
|
ReadTimeout = 30 * time.Second
|
||||||
// WriteTimeout is the timeout for writing.
|
// WriteTimeout is the timeout for writing.
|
||||||
WriteTimeout = 90 * time.Second
|
WriteTimeout = 60 * time.Second
|
||||||
// default udp node TTL in second for udp port forwarding.
|
// default udp node TTL in second for udp port forwarding.
|
||||||
defaultTTL = 60
|
defaultTTL = 60
|
||||||
)
|
)
|
||||||
|
@ -87,6 +87,8 @@ func HTTPHandler(opts ...HandlerOption) Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *httpHandler) Handle(conn net.Conn) {
|
func (h *httpHandler) Handle(conn net.Conn) {
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
req, err := http.ReadRequest(bufio.NewReader(conn))
|
req, err := http.ReadRequest(bufio.NewReader(conn))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log("[http]", err)
|
log.Log("[http]", err)
|
||||||
|
@ -19,8 +19,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// SALT is the default salt for KCP cipher.
|
// KCPSalt is the default salt for KCP cipher.
|
||||||
SALT = "kcp-go"
|
KCPSalt = "kcp-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
// KCPConfig describes the config for KCP.
|
// KCPConfig describes the config for KCP.
|
||||||
@ -204,7 +204,7 @@ func (tr *kcpTransporter) Dial(addr string) (conn net.Conn, err error) {
|
|||||||
|
|
||||||
func (tr *kcpTransporter) dial(addr string, config *KCPConfig) (*kcpSession, error) {
|
func (tr *kcpTransporter) dial(addr string, config *KCPConfig) (*kcpSession, error) {
|
||||||
kcpconn, err := kcp.DialWithOptions(addr,
|
kcpconn, err := kcp.DialWithOptions(addr,
|
||||||
blockCrypt(config.Key, config.Crypt, SALT), config.DataShard, config.ParityShard)
|
blockCrypt(config.Key, config.Crypt, KCPSalt), config.DataShard, config.ParityShard)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -260,7 +260,7 @@ func KCPListener(addr string, config *KCPConfig) (Listener, error) {
|
|||||||
config.Init()
|
config.Init()
|
||||||
|
|
||||||
ln, err := kcp.ListenWithOptions(addr,
|
ln, err := kcp.ListenWithOptions(addr,
|
||||||
blockCrypt(config.Key, config.Crypt, SALT), config.DataShard, config.ParityShard)
|
blockCrypt(config.Key, config.Crypt, KCPSalt), config.DataShard, config.ParityShard)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
package gost
|
package gost
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
// Node is a proxy node, mainly used to construct a proxy chain.
|
// Node is a proxy node, mainly used to construct a proxy chain.
|
||||||
type Node struct {
|
type Node struct {
|
||||||
Addr string
|
Addr string
|
||||||
Protocol string
|
Protocol string
|
||||||
Transport string
|
Transport string
|
||||||
|
User *url.Userinfo
|
||||||
Client *Client
|
Client *Client
|
||||||
}
|
}
|
||||||
|
91
gost/redirect.go
Normal file
91
gost/redirect.go
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package gost
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/go-log/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type tcpRedirectHandler struct {
|
||||||
|
options *HandlerOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// TCPRedirectHandler creates a server Handler for TCP redirect server.
|
||||||
|
func TCPRedirectHandler(opts ...HandlerOption) Handler {
|
||||||
|
h := &tcpRedirectHandler{
|
||||||
|
options: &HandlerOptions{
|
||||||
|
Chain: new(Chain),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(h.options)
|
||||||
|
}
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *tcpRedirectHandler) Handle(c net.Conn) {
|
||||||
|
conn, ok := c.(*net.TCPConn)
|
||||||
|
if !ok {
|
||||||
|
log.Log("[red-tcp] not a TCP connection")
|
||||||
|
}
|
||||||
|
|
||||||
|
srcAddr := conn.RemoteAddr()
|
||||||
|
dstAddr, conn, err := h.getOriginalDstAddr(conn)
|
||||||
|
if err != nil {
|
||||||
|
log.Logf("[red-tcp] %s -> %s : %s", srcAddr, dstAddr, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
log.Logf("[red-tcp] %s -> %s", srcAddr, dstAddr)
|
||||||
|
|
||||||
|
cc, err := h.options.Chain.Dial(dstAddr.String())
|
||||||
|
if err != nil {
|
||||||
|
log.Logf("[red-tcp] %s -> %s : %s", srcAddr, dstAddr, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer cc.Close()
|
||||||
|
|
||||||
|
log.Logf("[red-tcp] %s <-> %s", srcAddr, dstAddr)
|
||||||
|
transport(conn, cc)
|
||||||
|
log.Logf("[red-tcp] %s >-< %s", srcAddr, dstAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *tcpRedirectHandler) getOriginalDstAddr(conn *net.TCPConn) (addr net.Addr, c *net.TCPConn, err error) {
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
fc, err := conn.File()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer fc.Close()
|
||||||
|
|
||||||
|
mreq, err := syscall.GetsockoptIPv6Mreq(int(fc.Fd()), syscall.IPPROTO_IP, 80)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// only ipv4 support
|
||||||
|
ip := net.IPv4(mreq.Multiaddr[4], mreq.Multiaddr[5], mreq.Multiaddr[6], mreq.Multiaddr[7])
|
||||||
|
port := uint16(mreq.Multiaddr[2])<<8 + uint16(mreq.Multiaddr[3])
|
||||||
|
addr, err = net.ResolveTCPAddr("tcp4", fmt.Sprintf("%s:%d", ip.String(), port))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cc, err := net.FileConn(fc)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c, ok := cc.(*net.TCPConn)
|
||||||
|
if !ok {
|
||||||
|
err = errors.New("not a TCP connection")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
31
gost/redirect_win.go
Normal file
31
gost/redirect_win.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
package gost
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/go-log/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type tcpRedirectHandler struct {
|
||||||
|
options *HandlerOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// TCPRedirectHandler creates a server Handler for TCP redirect server.
|
||||||
|
func TCPRedirectHandler(opts ...HandlerOption) Handler {
|
||||||
|
h := &tcpRedirectHandler{
|
||||||
|
options: &HandlerOptions{
|
||||||
|
Chain: new(Chain),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(h.options)
|
||||||
|
}
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *tcpRedirectHandler) Handle(c net.Conn) {
|
||||||
|
log.Log("[red-tcp] TCP redirect is not available on the Windows platform")
|
||||||
|
c.Close()
|
||||||
|
}
|
@ -365,6 +365,8 @@ func SOCKS5Handler(opts ...HandlerOption) Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *socks5Handler) Handle(conn net.Conn) {
|
func (h *socks5Handler) Handle(conn net.Conn) {
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
conn = gosocks5.ServerConn(conn, h.selector)
|
conn = gosocks5.ServerConn(conn, h.selector)
|
||||||
req, err := gosocks5.ReadRequest(conn)
|
req, err := gosocks5.ReadRequest(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -960,6 +962,8 @@ func SOCKS4Handler(opts ...HandlerOption) Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *socks4Handler) Handle(conn net.Conn) {
|
func (h *socks4Handler) Handle(conn net.Conn) {
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
req, err := gosocks4.ReadRequest(conn)
|
req, err := gosocks4.ReadRequest(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log("[socks4]", err)
|
log.Log("[socks4]", err)
|
||||||
|
127
gost/srv/srv.go
127
gost/srv/srv.go
@ -6,8 +6,6 @@ import (
|
|||||||
|
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/ginuerzh/gost/gost"
|
"github.com/ginuerzh/gost/gost"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,27 +15,22 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
wg := sync.WaitGroup{}
|
go httpServer()
|
||||||
wg.Add(1)
|
go socks5Server()
|
||||||
go httpServer(&wg)
|
go tlsServer()
|
||||||
wg.Add(1)
|
go shadowServer()
|
||||||
go socks5Server(&wg)
|
go wsServer()
|
||||||
wg.Add(1)
|
go wssServer()
|
||||||
go tlsServer(&wg)
|
go kcpServer()
|
||||||
wg.Add(1)
|
go tcpForwardServer()
|
||||||
go shadowServer(&wg)
|
go rtcpForwardServer()
|
||||||
wg.Add(1)
|
// go rudpForwardServer()
|
||||||
go wsServer(&wg)
|
go tcpRedirectServer()
|
||||||
wg.Add(1)
|
|
||||||
go wssServer(&wg)
|
select {}
|
||||||
wg.Add(1)
|
|
||||||
go kcpServer(&wg)
|
|
||||||
wg.Wait()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func httpServer(wg *sync.WaitGroup) {
|
func httpServer() {
|
||||||
defer wg.Done()
|
|
||||||
|
|
||||||
s := &gost.Server{}
|
s := &gost.Server{}
|
||||||
s.Handle(gost.HTTPHandler(
|
s.Handle(gost.HTTPHandler(
|
||||||
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
||||||
@ -49,9 +42,7 @@ func httpServer(wg *sync.WaitGroup) {
|
|||||||
log.Fatal(s.Serve(ln))
|
log.Fatal(s.Serve(ln))
|
||||||
}
|
}
|
||||||
|
|
||||||
func socks5Server(wg *sync.WaitGroup) {
|
func socks5Server() {
|
||||||
defer wg.Done()
|
|
||||||
|
|
||||||
cert, err := tls.LoadX509KeyPair("cert.pem", "key.pem")
|
cert, err := tls.LoadX509KeyPair("cert.pem", "key.pem")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@ -69,9 +60,7 @@ func socks5Server(wg *sync.WaitGroup) {
|
|||||||
log.Fatal(s.Serve(ln))
|
log.Fatal(s.Serve(ln))
|
||||||
}
|
}
|
||||||
|
|
||||||
func shadowServer(wg *sync.WaitGroup) {
|
func shadowServer() {
|
||||||
defer wg.Done()
|
|
||||||
|
|
||||||
s := &gost.Server{}
|
s := &gost.Server{}
|
||||||
s.Handle(gost.ShadowHandler(
|
s.Handle(gost.ShadowHandler(
|
||||||
gost.UsersHandlerOption(url.UserPassword("chacha20", "123456")),
|
gost.UsersHandlerOption(url.UserPassword("chacha20", "123456")),
|
||||||
@ -83,9 +72,7 @@ func shadowServer(wg *sync.WaitGroup) {
|
|||||||
log.Fatal(s.Serve(ln))
|
log.Fatal(s.Serve(ln))
|
||||||
}
|
}
|
||||||
|
|
||||||
func tlsServer(wg *sync.WaitGroup) {
|
func tlsServer() {
|
||||||
defer wg.Done()
|
|
||||||
|
|
||||||
s := &gost.Server{}
|
s := &gost.Server{}
|
||||||
s.Handle(gost.HTTPHandler(
|
s.Handle(gost.HTTPHandler(
|
||||||
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
||||||
@ -101,9 +88,7 @@ func tlsServer(wg *sync.WaitGroup) {
|
|||||||
log.Fatal(s.Serve(ln))
|
log.Fatal(s.Serve(ln))
|
||||||
}
|
}
|
||||||
|
|
||||||
func wsServer(wg *sync.WaitGroup) {
|
func wsServer() {
|
||||||
defer wg.Done()
|
|
||||||
|
|
||||||
s := &gost.Server{}
|
s := &gost.Server{}
|
||||||
s.Handle(gost.HTTPHandler(
|
s.Handle(gost.HTTPHandler(
|
||||||
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
||||||
@ -115,9 +100,7 @@ func wsServer(wg *sync.WaitGroup) {
|
|||||||
log.Fatal(s.Serve(ln))
|
log.Fatal(s.Serve(ln))
|
||||||
}
|
}
|
||||||
|
|
||||||
func wssServer(wg *sync.WaitGroup) {
|
func wssServer() {
|
||||||
defer wg.Done()
|
|
||||||
|
|
||||||
s := &gost.Server{}
|
s := &gost.Server{}
|
||||||
s.Handle(gost.HTTPHandler(
|
s.Handle(gost.HTTPHandler(
|
||||||
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
||||||
@ -134,9 +117,7 @@ func wssServer(wg *sync.WaitGroup) {
|
|||||||
log.Fatal(s.Serve(ln))
|
log.Fatal(s.Serve(ln))
|
||||||
}
|
}
|
||||||
|
|
||||||
func kcpServer(wg *sync.WaitGroup) {
|
func kcpServer() {
|
||||||
defer wg.Done()
|
|
||||||
|
|
||||||
s := &gost.Server{}
|
s := &gost.Server{}
|
||||||
s.Handle(gost.HTTPHandler())
|
s.Handle(gost.HTTPHandler())
|
||||||
ln, err := gost.KCPListener(":8388", nil)
|
ln, err := gost.KCPListener(":8388", nil)
|
||||||
@ -145,3 +126,71 @@ func kcpServer(wg *sync.WaitGroup) {
|
|||||||
}
|
}
|
||||||
log.Fatal(s.Serve(ln))
|
log.Fatal(s.Serve(ln))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func tcpForwardServer() {
|
||||||
|
s := &gost.Server{}
|
||||||
|
s.Handle(gost.TCPForwardHandler("ginuerzh.xyz:22"))
|
||||||
|
ln, err := gost.TCPListener(":2222")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
log.Fatal(s.Serve(ln))
|
||||||
|
}
|
||||||
|
|
||||||
|
func rtcpForwardServer() {
|
||||||
|
s := &gost.Server{}
|
||||||
|
s.Handle(gost.RTCPForwardHandler(":1222", "ginuerzh.xyz:22"))
|
||||||
|
ln, err := gost.RTCPForwardListener(
|
||||||
|
":1222",
|
||||||
|
gost.NewChain(
|
||||||
|
gost.Node{
|
||||||
|
Protocol: "socks5",
|
||||||
|
Transport: "tcp",
|
||||||
|
Addr: "localhost:12345",
|
||||||
|
User: url.UserPassword("admin", "123456"),
|
||||||
|
Client: gost.NewClient(
|
||||||
|
gost.SOCKS5Connector(url.UserPassword("admin", "123456")),
|
||||||
|
gost.TCPTransporter(),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal()
|
||||||
|
}
|
||||||
|
log.Fatal(s.Serve(ln))
|
||||||
|
}
|
||||||
|
|
||||||
|
func rudpForwardServer() {
|
||||||
|
s := &gost.Server{}
|
||||||
|
s.Handle(gost.RUDPForwardHandler(":10053", "localhost:53"))
|
||||||
|
ln, err := gost.RUDPForwardListener(
|
||||||
|
":10053",
|
||||||
|
gost.NewChain(
|
||||||
|
gost.Node{
|
||||||
|
Protocol: "socks5",
|
||||||
|
Transport: "tcp",
|
||||||
|
Addr: "localhost:12345",
|
||||||
|
User: url.UserPassword("admin", "123456"),
|
||||||
|
Client: gost.NewClient(
|
||||||
|
gost.SOCKS5Connector(url.UserPassword("admin", "123456")),
|
||||||
|
gost.TCPTransporter(),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal()
|
||||||
|
}
|
||||||
|
log.Fatal(s.Serve(ln))
|
||||||
|
}
|
||||||
|
|
||||||
|
func tcpRedirectServer() {
|
||||||
|
s := &gost.Server{}
|
||||||
|
s.Handle(gost.TCPRedirectHandler())
|
||||||
|
ln, err := gost.TCPListener(":8008")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
log.Fatal(s.Serve(ln))
|
||||||
|
}
|
||||||
|
@ -106,6 +106,8 @@ func ShadowHandler(opts ...HandlerOption) Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *shadowHandler) Handle(conn net.Conn) {
|
func (h *shadowHandler) Handle(conn net.Conn) {
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
var method, password string
|
var method, password string
|
||||||
|
|
||||||
users := h.options.Users
|
users := h.options.Users
|
||||||
|
Loading…
Reference in New Issue
Block a user