experimental quic support
This commit is contained in:
parent
6ca1f4a984
commit
e0b8e54619
2
gost.go
2
gost.go
@ -11,7 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Version = "2.2-rc2"
|
Version = "2.3-dev"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Log level for glog
|
// Log level for glog
|
||||||
|
2
node.go
2
node.go
@ -57,7 +57,7 @@ func ParseProxyNode(s string) (node ProxyNode, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch node.Transport {
|
switch node.Transport {
|
||||||
case "ws", "wss", "tls", "http2":
|
case "ws", "wss", "tls", "http2", "ssu", "quic":
|
||||||
case "https":
|
case "https":
|
||||||
node.Protocol = "http"
|
node.Protocol = "http"
|
||||||
node.Transport = "tls"
|
node.Transport = "tls"
|
||||||
|
80
quic.go
Normal file
80
quic.go
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
package gost
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"crypto/tls"
|
||||||
|
"github.com/golang/glog"
|
||||||
|
"github.com/lucas-clemente/quic-go/h2quic"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
type QuicServer struct {
|
||||||
|
Base *ProxyServer
|
||||||
|
Handler http.Handler
|
||||||
|
TLSConfig *tls.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewQuicServer(base *ProxyServer) *QuicServer {
|
||||||
|
return &QuicServer{Base: base}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *QuicServer) ListenAndServeTLS(config *tls.Config) error {
|
||||||
|
server := &h2quic.Server{
|
||||||
|
Server: &http.Server{
|
||||||
|
Addr: s.Base.Node.Addr,
|
||||||
|
Handler: s.Handler,
|
||||||
|
TLSConfig: config,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if server.Handler == nil {
|
||||||
|
server.Handler = http.HandlerFunc(s.HandleRequest)
|
||||||
|
}
|
||||||
|
return server.ListenAndServe()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *QuicServer) HandleRequest(w http.ResponseWriter, req *http.Request) {
|
||||||
|
target := req.Host
|
||||||
|
glog.V(LINFO).Infof("[quic] %s %s - %s %s", req.Method, req.RemoteAddr, target, req.Proto)
|
||||||
|
|
||||||
|
if glog.V(LDEBUG) {
|
||||||
|
dump, _ := httputil.DumpRequest(req, false)
|
||||||
|
glog.Infoln(string(dump))
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := s.Base.Chain.Dial(target)
|
||||||
|
if err != nil {
|
||||||
|
glog.V(LWARNING).Infof("[quic] %s -> %s : %s", req.RemoteAddr, target, err)
|
||||||
|
w.WriteHeader(http.StatusServiceUnavailable)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
glog.V(LINFO).Infof("[quic] %s <-> %s", req.RemoteAddr, target)
|
||||||
|
|
||||||
|
req.Header.Set("Connection", "Keep-Alive")
|
||||||
|
if err = req.Write(c); err != nil {
|
||||||
|
glog.V(LWARNING).Infof("[quic] %s -> %s : %s", req.RemoteAddr, target, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := http.ReadResponse(bufio.NewReader(c), req)
|
||||||
|
if err != nil {
|
||||||
|
glog.V(LWARNING).Infoln(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
for k, v := range resp.Header {
|
||||||
|
for _, vv := range v {
|
||||||
|
w.Header().Add(k, vv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w.WriteHeader(resp.StatusCode)
|
||||||
|
if _, err := io.Copy(flushWriter{w}, resp.Body); err != nil {
|
||||||
|
glog.V(LWARNING).Infof("[quic] %s <- %s : %s", req.RemoteAddr, target, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
glog.V(LINFO).Infof("[quic] %s >-< %s", req.RemoteAddr, target)
|
||||||
|
}
|
@ -80,6 +80,10 @@ func (s *ProxyServer) Serve() error {
|
|||||||
return NewRTcpForwardServer(s).Serve()
|
return NewRTcpForwardServer(s).Serve()
|
||||||
case "rudp": // Remote UDP port forwarding
|
case "rudp": // Remote UDP port forwarding
|
||||||
return NewRUdpForwardServer(s).Serve()
|
return NewRUdpForwardServer(s).Serve()
|
||||||
|
case "ssu": // shadowsocks udp relay
|
||||||
|
return NewShadowUdpServer(s).ListenAndServe()
|
||||||
|
case "quic":
|
||||||
|
return NewQuicServer(s).ListenAndServeTLS(s.TLSConfig)
|
||||||
default:
|
default:
|
||||||
ln, err = net.Listen("tcp", node.Addr)
|
ln, err = net.Listen("tcp", node.Addr)
|
||||||
}
|
}
|
||||||
|
40
ss.go
40
ss.go
@ -65,6 +65,46 @@ func (s *ShadowServer) Serve() {
|
|||||||
glog.V(LINFO).Infof("[ss] %s >-< %s", s.conn.RemoteAddr(), addr)
|
glog.V(LINFO).Infof("[ss] %s >-< %s", s.conn.RemoteAddr(), addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ShadowUdpServer struct {
|
||||||
|
Base *ProxyServer
|
||||||
|
Handler func(conn *net.UDPConn, addr *net.UDPAddr, data []byte)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewShadowUdpServer(base *ProxyServer) *ShadowUdpServer {
|
||||||
|
return &ShadowUdpServer{Base: base}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ShadowUdpServer) ListenAndServe() error {
|
||||||
|
laddr, err := net.ResolveUDPAddr("udp", s.Base.Node.Addr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
lconn, err := net.ListenUDP("udp", laddr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer lconn.Close()
|
||||||
|
|
||||||
|
if s.Handler == nil {
|
||||||
|
s.Handler = s.HandleConn
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
b := make([]byte, LargeBufferSize)
|
||||||
|
n, addr, err := lconn.ReadFromUDP(b)
|
||||||
|
if err != nil {
|
||||||
|
glog.V(LWARNING).Infoln(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
go s.Handler(lconn, addr, b[:n])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ShadowUdpServer) HandleConn(conn *net.UDPConn, addr *net.UDPAddr, data []byte) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// This function is copied from shadowsocks library with some modification.
|
// This function is copied from shadowsocks library with some modification.
|
||||||
func (s *ShadowServer) getRequest() (host string, ota bool, err error) {
|
func (s *ShadowServer) getRequest() (host string, ota bool, err error) {
|
||||||
// buf size should at least have the same size with the largest possible
|
// buf size should at least have the same size with the largest possible
|
||||||
|
Loading…
Reference in New Issue
Block a user