gost_software/gost/forward.go
2017-07-28 13:45:19 +08:00

383 lines
8.5 KiB
Go

package gost
import (
"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
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
}
return &rtcpForwardListener{
addr: laddr,
chain: chain,
close: make(chan struct{}),
}, nil
}
func (l *rtcpForwardListener) 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
}
return cc, nil
}
func (l *rtcpForwardListener) handshake(conn net.Conn) (net.Conn, error) {
conn, err := socks5Handshake(conn, l.chain.LastNode().User)
if err != nil {
return nil, err
}
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
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
}
return &rudpForwardListener{
addr: laddr,
chain: chain,
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) {
conn, err := socks5Handshake(conn, l.chain.LastNode().User)
if err != nil {
return nil, err
}
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
}