fix port forwarding

This commit is contained in:
rui.zheng 2016-10-05 21:05:51 +08:00
parent 6baa9960f4
commit 0991952f0c
3 changed files with 84 additions and 31 deletions

View File

@ -48,6 +48,19 @@ func (c *ProxyChain) Nodes() []ProxyNode {
return c.nodes return c.nodes
} }
func (c *ProxyChain) GetNode(index int) *ProxyNode {
if index < len(c.nodes) {
return &c.nodes[index]
}
return nil
}
func (c *ProxyChain) SetNode(index int, node ProxyNode) {
if index < len(c.nodes) {
c.nodes[index] = node
}
}
// TryEnableHttp2 initialize HTTP2 if available. // TryEnableHttp2 initialize HTTP2 if available.
// HTTP2 will be enabled when at least one HTTP2 proxy node (scheme == http2) is present. // HTTP2 will be enabled when at least one HTTP2 proxy node (scheme == http2) is present.
// //
@ -63,7 +76,7 @@ func (c *ProxyChain) TryEnableHttp2() {
// HTTP2 restrict: HTTP2 will be enabled when at least one HTTP2 proxy node is present. // HTTP2 restrict: HTTP2 will be enabled when at least one HTTP2 proxy node is present.
for i, node := range c.nodes { for i, node := range c.nodes {
if node.Transport == "http2" { if node.Transport == "http2" {
glog.V(LINFO).Infoln("http2 enabled") glog.V(LINFO).Infoln("HTTP2 enabled")
cfg := &tls.Config{ cfg := &tls.Config{
InsecureSkipVerify: node.insecureSkipVerify(), InsecureSkipVerify: node.insecureSkipVerify(),
ServerName: node.serverName, ServerName: node.serverName,

47
http.go
View File

@ -3,13 +3,13 @@ package gost
import ( import (
"bufio" "bufio"
"crypto/tls" "crypto/tls"
"encoding/base64"
"github.com/golang/glog" "github.com/golang/glog"
"golang.org/x/net/http2" "golang.org/x/net/http2"
"io" "io"
"net" "net"
"net/http" "net/http"
"net/http/httputil" "net/http/httputil"
//"encoding/base64"
//"strings" //"strings"
"errors" "errors"
"time" "time"
@ -62,15 +62,11 @@ func (s *HttpServer) HandleRequest(req *http.Request) {
} }
// TODO: forward http request // TODO: forward http request
/* lastNode := s.Base.Chain.lastNode
if len(forwardArgs) > 0 { if lastNode != nil && (lastNode.Protocol == "http" || lastNode.Protocol == "") {
last := forwardArgs[len(forwardArgs)-1] s.forwardRequest(req)
if last.Protocol == "http" || last.Protocol == "" {
forwardHttpRequest(req, conn, arg)
return return
} }
}
*/
c, err := s.Base.Chain.Dial(req.Host) c, err := s.Base.Chain.Dial(req.Host)
if err != nil { if err != nil {
@ -104,6 +100,41 @@ func (s *HttpServer) HandleRequest(req *http.Request) {
glog.V(LINFO).Infof("[http] %s >-< %s", s.conn.RemoteAddr(), req.Host) glog.V(LINFO).Infof("[http] %s >-< %s", s.conn.RemoteAddr(), req.Host)
} }
func (s *HttpServer) forwardRequest(req *http.Request) {
last := s.Base.Chain.lastNode
if last == nil {
return
}
cc, err := s.Base.Chain.GetConn()
if err != nil {
glog.V(LWARNING).Infof("[http] %s -> %s : %s", s.conn.RemoteAddr(), last.Addr, err)
b := []byte("HTTP/1.1 503 Service unavailable\r\n" +
"Proxy-Agent: gost/" + Version + "\r\n\r\n")
glog.V(LDEBUG).Infof("[http] %s <- %s\n%s", s.conn.RemoteAddr(), last.Addr, string(b))
s.conn.Write(b)
return
}
defer cc.Close()
if last.User != nil {
req.Header.Set("Proxy-Authorization",
"Basic "+base64.StdEncoding.EncodeToString([]byte(last.User.String())))
}
cc.SetWriteDeadline(time.Now().Add(WriteTimeout))
if err = req.WriteProxy(cc); err != nil {
glog.V(LWARNING).Infof("[http] %s -> %s : %s", s.conn.RemoteAddr(), req.Host, err)
return
}
cc.SetWriteDeadline(time.Time{})
glog.V(LINFO).Infof("[http] %s <-> %s", s.conn.RemoteAddr(), req.Host)
s.Base.transport(s.conn, cc)
glog.V(LINFO).Infof("[http] %s >-< %s", s.conn.RemoteAddr(), req.Host)
return
}
type Http2Server struct { type Http2Server struct {
Base *ProxyServer Base *ProxyServer
Handler http.Handler Handler http.Handler

View File

@ -316,54 +316,63 @@ func (s *Socks5Server) handleUDPRelay(req *gosocks5.Request) {
cc, err := s.Base.Chain.GetConn() cc, err := s.Base.Chain.GetConn()
// connection error // connection error
if err != nil && err != ErrEmptyChain { if err != nil && err != ErrEmptyChain {
glog.V(LWARNING).Infof("[udp] %s -> %s : %s", s.conn.RemoteAddr(), req.Addr, err) glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), socksAddr, err)
return return
} }
// serve as standard socks5 udp relay // serve as standard socks5 udp relay local <-> remote
if err == ErrEmptyChain { if err == ErrEmptyChain {
peer, err := net.ListenUDP("udp", nil) peer, er := net.ListenUDP("udp", nil)
if err != nil { if er != nil {
glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), req.Addr, err) glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), socksAddr, er)
return return
} }
defer peer.Close() defer peer.Close()
go s.transportUDP(relay, peer) go s.transportUDP(relay, peer)
} }
// forward udp local <-> tunnel
if err == nil { if err == nil {
defer cc.Close() defer cc.Close()
cc.SetWriteDeadline(time.Now().Add(WriteTimeout)) cc.SetWriteDeadline(time.Now().Add(WriteTimeout))
if err := gosocks5.NewRequest(CmdUdpTun, nil).Write(cc); err != nil { req := gosocks5.NewRequest(CmdUdpTun, nil)
glog.V(LWARNING).Infoln("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), req.Addr, err) if err := req.Write(cc); err != nil {
glog.V(LWARNING).Infoln("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), cc.RemoteAddr(), err)
return return
} }
cc.SetWriteDeadline(time.Time{}) cc.SetWriteDeadline(time.Time{})
glog.V(LDEBUG).Infof("[socks5-udp] %s -> %s\n%s", s.conn.RemoteAddr(), cc.RemoteAddr(), req)
cc.SetReadDeadline(time.Now().Add(ReadTimeout)) cc.SetReadDeadline(time.Now().Add(ReadTimeout))
reply, err = gosocks5.ReadReply(cc) reply, err = gosocks5.ReadReply(cc)
if err != nil { if err != nil {
glog.V(LWARNING).Infoln("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), req.Addr, err) glog.V(LWARNING).Infoln("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), cc.RemoteAddr(), err)
return return
} }
glog.V(LDEBUG).Infof("[socks5-udp] %s <- %s\n%s", s.conn.RemoteAddr(), cc.RemoteAddr(), reply)
if reply.Rep != gosocks5.Succeeded { if reply.Rep != gosocks5.Succeeded {
glog.V(LWARNING).Infoln("[socks5-udp] %s -> %s : udp associate error", s.conn.RemoteAddr(), req.Addr) glog.V(LWARNING).Infoln("[socks5-udp] %s <- %s : udp associate failed", s.conn.RemoteAddr(), cc.RemoteAddr())
return return
} }
cc.SetReadDeadline(time.Time{}) cc.SetReadDeadline(time.Time{})
glog.V(LINFO).Infof("[socks5-udp] %s <-> %s [tun: %s]", s.conn.RemoteAddr(), socksAddr, reply.Addr)
go s.tunnelUDP(relay, cc, true) go s.tunnelUDP(relay, cc, true)
} }
glog.V(LINFO).Infof("[socks5-udp] %s <-> %s", s.conn.RemoteAddr(), req.Addr) glog.V(LINFO).Infof("[socks5-udp] %s <-> %s", s.conn.RemoteAddr(), socksAddr)
b := make([]byte, SmallBufferSize) b := make([]byte, SmallBufferSize)
for { for {
_, err := s.conn.Read(b) // discard any data from tcp connection _, err := s.conn.Read(b) // discard any data from tcp connection
if err != nil { if err != nil {
glog.V(LWARNING).Infof("[socks5-udp] %s - %s : %s", s.conn.RemoteAddr(), socksAddr, err)
break // client disconnected break // client disconnected
} }
} }
glog.V(LINFO).Infof("[socks5-udp] %s >-< %s", s.conn.RemoteAddr(), req.Addr) glog.V(LINFO).Infof("[socks5-udp] %s >-< %s", s.conn.RemoteAddr(), socksAddr)
} }
func (s *Socks5Server) handleUDPTunnel(req *gosocks5.Request) { func (s *Socks5Server) handleUDPTunnel(req *gosocks5.Request) {
@ -371,10 +380,10 @@ func (s *Socks5Server) handleUDPTunnel(req *gosocks5.Request) {
// connection error // connection error
if err != nil && err != ErrEmptyChain { if err != nil && err != ErrEmptyChain {
glog.V(LWARNING).Infof("[socks5-udp] %s <- %s : %s", s.conn.RemoteAddr(), req.Addr, err) glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), req.Addr, err)
reply := gosocks5.NewReply(gosocks5.Failure, nil) reply := gosocks5.NewReply(gosocks5.Failure, nil)
reply.Write(s.conn) reply.Write(s.conn)
glog.V(LDEBUG).Infof("[socks5-udp] %s <- %s\n%s", s.conn.RemoteAddr(), req.Addr, reply) glog.V(LDEBUG).Infof("[socks5-udp] %s -> %s\n%s", s.conn.RemoteAddr(), req.Addr, reply)
return return
} }
@ -383,7 +392,7 @@ func (s *Socks5Server) handleUDPTunnel(req *gosocks5.Request) {
bindAddr, _ := net.ResolveUDPAddr("udp", req.Addr.String()) bindAddr, _ := net.ResolveUDPAddr("udp", req.Addr.String())
uc, err := net.ListenUDP("udp", bindAddr) uc, err := net.ListenUDP("udp", bindAddr)
if err != nil { if err != nil {
glog.V(LWARNING).Infof("[socks5-udp] %s <- %s : %s", s.conn.RemoteAddr(), req.Addr, err) glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), req.Addr, err)
return return
} }
defer uc.Close() defer uc.Close()
@ -392,14 +401,14 @@ func (s *Socks5Server) handleUDPTunnel(req *gosocks5.Request) {
socksAddr.Host, _, _ = net.SplitHostPort(s.conn.LocalAddr().String()) socksAddr.Host, _, _ = net.SplitHostPort(s.conn.LocalAddr().String())
reply := gosocks5.NewReply(gosocks5.Succeeded, socksAddr) reply := gosocks5.NewReply(gosocks5.Succeeded, socksAddr)
if err := reply.Write(s.conn); err != nil { if err := reply.Write(s.conn); err != nil {
glog.V(LWARNING).Infof("[socks5-udp] %s <- %s : %s", s.conn.RemoteAddr(), req.Addr, err) glog.V(LWARNING).Infof("[socks5-udp] %s <- %s : %s", s.conn.RemoteAddr(), socksAddr, err)
return return
} }
glog.V(LDEBUG).Infof("[socks5-udp] %s <- %s\n%s", s.conn.RemoteAddr(), uc.LocalAddr(), reply) glog.V(LDEBUG).Infof("[socks5-udp] %s <- %s\n%s", s.conn.RemoteAddr(), socksAddr, reply)
glog.V(LINFO).Infof("[socks5-udp] %s <-> %s", s.conn.RemoteAddr(), uc.LocalAddr()) glog.V(LINFO).Infof("[socks5-udp] %s <-> %s", s.conn.RemoteAddr(), socksAddr)
s.tunnelUDP(uc, s.conn, false) s.tunnelUDP(uc, s.conn, false)
glog.V(LINFO).Infof("[socks5-udp] %s >-< %s", s.conn.RemoteAddr(), uc.LocalAddr()) glog.V(LINFO).Infof("[socks5-udp] %s >-< %s", s.conn.RemoteAddr(), socksAddr)
return return
} }