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
}
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.
// 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.
for i, node := range c.nodes {
if node.Transport == "http2" {
glog.V(LINFO).Infoln("http2 enabled")
glog.V(LINFO).Infoln("HTTP2 enabled")
cfg := &tls.Config{
InsecureSkipVerify: node.insecureSkipVerify(),
ServerName: node.serverName,

47
http.go
View File

@ -3,13 +3,13 @@ package gost
import (
"bufio"
"crypto/tls"
"encoding/base64"
"github.com/golang/glog"
"golang.org/x/net/http2"
"io"
"net"
"net/http"
"net/http/httputil"
//"encoding/base64"
//"strings"
"errors"
"time"
@ -62,15 +62,11 @@ func (s *HttpServer) HandleRequest(req *http.Request) {
}
// TODO: forward http request
/*
if len(forwardArgs) > 0 {
last := forwardArgs[len(forwardArgs)-1]
if last.Protocol == "http" || last.Protocol == "" {
forwardHttpRequest(req, conn, arg)
lastNode := s.Base.Chain.lastNode
if lastNode != nil && (lastNode.Protocol == "http" || lastNode.Protocol == "") {
s.forwardRequest(req)
return
}
}
*/
c, err := s.Base.Chain.Dial(req.Host)
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)
}
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 {
Base *ProxyServer
Handler http.Handler

View File

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