#61 add transparent proxy support

This commit is contained in:
rui.zheng 2017-01-04 12:50:22 +08:00
parent a06495282e
commit 62d92d953a
4 changed files with 105 additions and 2 deletions

View File

@ -265,7 +265,7 @@ gost -L=:8080 -F=ss://aes-128-cfb:123456@server_ip:8338
#### TLS #### TLS
There is built-in TLS certificate in gost, if you need to use other TLS certificate, there are two ways: There is built-in TLS certificate in gost, if you need to use other TLS certificate, there are two ways:
* Place two files cert.pem (public key) and key.pem (private key) in the current working directory, gost will automatically load them. * Place two files cert.pem (public key) and key.pem (private key) in the current working directory, gost will automatically load them.
* Use the parameter to specify the path to the certificate file * Use the parameter to specify the path to the certificate file:
```bash ```bash
gost -L="http2://:443?cert=/path/to/my/cert/file&key=/path/to/my/key/file" gost -L="http2://:443?cert=/path/to/my/cert/file&key=/path/to/my/key/file"
``` ```

View File

@ -71,7 +71,7 @@ func ParseProxyNode(s string) (node ProxyNode, err error) {
} }
switch node.Transport { switch node.Transport {
case "ws", "wss", "tls", "http2", "ssu", "quic", "kcp": case "ws", "wss", "tls", "http2", "ssu", "quic", "kcp", "redirect":
case "https": case "https":
node.Protocol = "http" node.Protocol = "http"
node.Transport = "tls" node.Transport = "tls"

101
redirect.go Normal file
View File

@ -0,0 +1,101 @@
package gost
import (
"errors"
"fmt"
"github.com/golang/glog"
"net"
"syscall"
)
const (
SO_ORIGINAL_DST = 80
)
type RedsocksTCPServer struct {
Base *ProxyServer
}
func NewRedsocksTCPServer(base *ProxyServer) *RedsocksTCPServer {
return &RedsocksTCPServer{
Base: base,
}
}
func (s *RedsocksTCPServer) ListenAndServe() error {
laddr, err := net.ResolveTCPAddr("tcp", s.Base.Node.Addr)
if err != nil {
return err
}
ln, err := net.ListenTCP("tcp", laddr)
if err != nil {
return err
}
defer ln.Close()
for {
conn, err := ln.AcceptTCP()
if err != nil {
glog.V(LWARNING).Infoln(err)
continue
}
go s.handleRedirectTCP(conn)
}
}
func (s *RedsocksTCPServer) handleRedirectTCP(conn *net.TCPConn) {
srcAddr := conn.RemoteAddr()
dstAddr, conn, err := getOriginalDstAddr(conn)
if err != nil {
glog.V(LWARNING).Infof("[red-tcp] %s -> %s : %s", srcAddr, dstAddr, err)
return
}
defer conn.Close()
glog.V(LINFO).Infof("[red-tcp] %s -> %s", srcAddr, dstAddr)
cc, err := s.Base.Chain.Dial(dstAddr.String())
if err != nil {
glog.V(LWARNING).Infof("[red-tcp] %s -> %s : %s", srcAddr, dstAddr, err)
return
}
defer cc.Close()
glog.V(LINFO).Infof("[red-tcp] %s <-> %s", srcAddr, dstAddr)
s.Base.transport(conn, cc)
glog.V(LINFO).Infof("[red-tcp] %s >-< %s", srcAddr, dstAddr)
}
func 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, SO_ORIGINAL_DST)
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
}

View File

@ -95,6 +95,8 @@ func (s *ProxyServer) Serve() error {
config.Key, _ = s.Node.Users[0].Password() config.Key, _ = s.Node.Users[0].Password()
} }
return NewKCPServer(s, config).ListenAndServe() return NewKCPServer(s, config).ListenAndServe()
case "redirect":
return NewRedsocksTCPServer(s).ListenAndServe()
default: default:
ln, err = net.Listen("tcp", node.Addr) ln, err = net.Listen("tcp", node.Addr)
} }