parse real client IP
This commit is contained in:
+10
-12
@@ -2,10 +2,10 @@ package v5
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"math"
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-gost/core/common/bufpool"
|
|
||||||
"github.com/go-gost/core/logger"
|
"github.com/go-gost/core/logger"
|
||||||
"github.com/go-gost/gosocks5"
|
"github.com/go-gost/gosocks5"
|
||||||
)
|
)
|
||||||
@@ -25,18 +25,17 @@ func (c *bindConn) RemoteAddr() net.Addr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type udpRelayConn struct {
|
type udpRelayConn struct {
|
||||||
udpConn *net.UDPConn
|
udpConn *net.UDPConn
|
||||||
tcpConn net.Conn
|
tcpConn net.Conn
|
||||||
taddr net.Addr
|
taddr net.Addr
|
||||||
bufferSize int
|
rbuf [math.MaxUint16]byte
|
||||||
logger logger.Logger
|
wbuf [math.MaxInt16]byte
|
||||||
|
logger logger.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *udpRelayConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
|
func (c *udpRelayConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
|
||||||
buf := bufpool.Get(c.bufferSize)
|
buf := c.rbuf[:]
|
||||||
defer bufpool.Put(buf)
|
nn, err := c.udpConn.Read(buf[:])
|
||||||
|
|
||||||
nn, err := c.udpConn.Read(buf)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -82,8 +81,7 @@ func (c *udpRelayConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
|
|||||||
Data: b,
|
Data: b,
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := bufpool.Get(c.bufferSize)
|
buf := c.wbuf[:]
|
||||||
defer bufpool.Put(buf)
|
|
||||||
|
|
||||||
nn, err := dgram.WriteTo(bytes.NewBuffer(buf[:0]))
|
nn, err := dgram.WriteTo(bytes.NewBuffer(buf[:0]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -225,10 +225,9 @@ func (c *socks5Connector) relayUDP(ctx context.Context, conn net.Conn, addr net.
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &udpRelayConn{
|
return &udpRelayConn{
|
||||||
udpConn: cc.(*net.UDPConn),
|
udpConn: cc.(*net.UDPConn),
|
||||||
tcpConn: conn,
|
tcpConn: conn,
|
||||||
taddr: addr,
|
taddr: addr,
|
||||||
bufferSize: c.md.udpBufferSize,
|
logger: log,
|
||||||
logger: log,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,19 +4,14 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
mdata "github.com/go-gost/core/metadata"
|
mdata "github.com/go-gost/core/metadata"
|
||||||
mdutil "github.com/go-gost/x/metadata/util"
|
|
||||||
"github.com/go-gost/x/internal/util/mux"
|
"github.com/go-gost/x/internal/util/mux"
|
||||||
)
|
mdutil "github.com/go-gost/x/metadata/util"
|
||||||
|
|
||||||
const (
|
|
||||||
defaultUDPBufferSize = 4096
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type metadata struct {
|
type metadata struct {
|
||||||
connectTimeout time.Duration
|
connectTimeout time.Duration
|
||||||
noTLS bool
|
noTLS bool
|
||||||
relay string
|
relay string
|
||||||
udpBufferSize int
|
|
||||||
udpTimeout time.Duration
|
udpTimeout time.Duration
|
||||||
muxCfg *mux.Config
|
muxCfg *mux.Config
|
||||||
}
|
}
|
||||||
@@ -25,10 +20,6 @@ func (c *socks5Connector) parseMetadata(md mdata.Metadata) (err error) {
|
|||||||
c.md.connectTimeout = mdutil.GetDuration(md, "timeout")
|
c.md.connectTimeout = mdutil.GetDuration(md, "timeout")
|
||||||
c.md.noTLS = mdutil.GetBool(md, "notls")
|
c.md.noTLS = mdutil.GetBool(md, "notls")
|
||||||
c.md.relay = mdutil.GetString(md, "relay")
|
c.md.relay = mdutil.GetString(md, "relay")
|
||||||
c.md.udpBufferSize = mdutil.GetInt(md, "udp.bufferSize", "udpBufferSize")
|
|
||||||
if c.md.udpBufferSize <= 0 {
|
|
||||||
c.md.udpBufferSize = defaultUDPBufferSize
|
|
||||||
}
|
|
||||||
c.md.udpTimeout = mdutil.GetDuration(md, "udp.timeout")
|
c.md.udpTimeout = mdutil.GetDuration(md, "udp.timeout")
|
||||||
|
|
||||||
c.md.muxCfg = &mux.Config{
|
c.md.muxCfg = &mux.Config{
|
||||||
|
|||||||
@@ -665,6 +665,11 @@ func (h *httpHandler) dial(ctx context.Context, network, addr string) (conn net.
|
|||||||
conn, err = h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &buf), network, addr)
|
conn, err = h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &buf), network, addr)
|
||||||
if ro := ctx_internal.RecorderObjectFromContext(ctx); ro != nil {
|
if ro := ctx_internal.RecorderObjectFromContext(ctx); ro != nil {
|
||||||
ro.Route = buf.String()
|
ro.Route = buf.String()
|
||||||
|
|
||||||
|
if conn != nil {
|
||||||
|
ro.Src = conn.LocalAddr().String()
|
||||||
|
ro.Dst = conn.RemoteAddr().String()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -49,9 +49,12 @@ type metadata struct {
|
|||||||
|
|
||||||
func (h *httpHandler) parseMetadata(md mdata.Metadata) error {
|
func (h *httpHandler) parseMetadata(md mdata.Metadata) error {
|
||||||
h.md.readTimeout = mdutil.GetDuration(md, "readTimeout")
|
h.md.readTimeout = mdutil.GetDuration(md, "readTimeout")
|
||||||
if h.md.readTimeout <= 0 {
|
if h.md.readTimeout == 0 {
|
||||||
h.md.readTimeout = 15 * time.Second
|
h.md.readTimeout = 15 * time.Second
|
||||||
}
|
}
|
||||||
|
if h.md.readTimeout < 0 {
|
||||||
|
h.md.readTimeout = 0
|
||||||
|
}
|
||||||
|
|
||||||
if m := mdutil.GetStringMapString(md, "http.header", "header"); len(m) > 0 {
|
if m := mdutil.GetStringMapString(md, "http.header", "header"); len(m) > 0 {
|
||||||
hd := http.Header{}
|
hd := http.Header{}
|
||||||
|
|||||||
@@ -87,6 +87,9 @@ func (h *socks5Handler) bindLocal(ctx context.Context, conn net.Conn, network, a
|
|||||||
|
|
||||||
// Issue: may not reachable when host has multi-interface
|
// Issue: may not reachable when host has multi-interface
|
||||||
socksAddr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String())
|
socksAddr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String())
|
||||||
|
if h.md.publicAddr != "" {
|
||||||
|
socksAddr.Host = h.md.publicAddr
|
||||||
|
}
|
||||||
socksAddr.Type = 0
|
socksAddr.Type = 0
|
||||||
reply := gosocks5.NewReply(gosocks5.Succeeded, &socksAddr)
|
reply := gosocks5.NewReply(gosocks5.Succeeded, &socksAddr)
|
||||||
log.Trace(reply)
|
log.Trace(reply)
|
||||||
|
|||||||
@@ -88,6 +88,9 @@ func (h *socks5Handler) muxBindLocal(ctx context.Context, conn net.Conn, network
|
|||||||
|
|
||||||
// Issue: may not reachable when host has multi-interface
|
// Issue: may not reachable when host has multi-interface
|
||||||
socksAddr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String())
|
socksAddr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String())
|
||||||
|
if h.md.publicAddr != "" {
|
||||||
|
socksAddr.Host = h.md.publicAddr
|
||||||
|
}
|
||||||
socksAddr.Type = 0
|
socksAddr.Type = 0
|
||||||
reply := gosocks5.NewReply(gosocks5.Succeeded, &socksAddr)
|
reply := gosocks5.NewReply(gosocks5.Succeeded, &socksAddr)
|
||||||
log.Trace(reply)
|
log.Trace(reply)
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type metadata struct {
|
type metadata struct {
|
||||||
|
publicAddr string
|
||||||
readTimeout time.Duration
|
readTimeout time.Duration
|
||||||
noTLS bool
|
noTLS bool
|
||||||
enableBind bool
|
enableBind bool
|
||||||
@@ -40,6 +41,7 @@ type metadata struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *socks5Handler) parseMetadata(md mdata.Metadata) (err error) {
|
func (h *socks5Handler) parseMetadata(md mdata.Metadata) (err error) {
|
||||||
|
h.md.publicAddr = mdutil.GetString(md, "socks.publicAddr", "publicAddr")
|
||||||
h.md.readTimeout = mdutil.GetDuration(md, "readTimeout")
|
h.md.readTimeout = mdutil.GetDuration(md, "readTimeout")
|
||||||
if h.md.readTimeout <= 0 {
|
if h.md.readTimeout <= 0 {
|
||||||
h.md.readTimeout = 15 * time.Second
|
h.md.readTimeout = 15 * time.Second
|
||||||
|
|||||||
+18
-10
@@ -17,6 +17,7 @@ import (
|
|||||||
"github.com/go-gost/x/internal/net/udp"
|
"github.com/go-gost/x/internal/net/udp"
|
||||||
"github.com/go-gost/x/internal/util/socks"
|
"github.com/go-gost/x/internal/util/socks"
|
||||||
traffic_wrapper "github.com/go-gost/x/limiter/traffic/wrapper"
|
traffic_wrapper "github.com/go-gost/x/limiter/traffic/wrapper"
|
||||||
|
metrics "github.com/go-gost/x/metrics/wrapper"
|
||||||
xstats "github.com/go-gost/x/observer/stats"
|
xstats "github.com/go-gost/x/observer/stats"
|
||||||
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
||||||
xrecorder "github.com/go-gost/x/recorder"
|
xrecorder "github.com/go-gost/x/recorder"
|
||||||
@@ -37,8 +38,8 @@ func (h *socks5Handler) handleUDP(ctx context.Context, conn net.Conn, ro *xrecor
|
|||||||
lc := xnet.ListenConfig{
|
lc := xnet.ListenConfig{
|
||||||
Netns: h.options.Netns,
|
Netns: h.options.Netns,
|
||||||
}
|
}
|
||||||
laddr := &net.UDPAddr{IP: conn.LocalAddr().(*net.TCPAddr).IP, Port: 0} // use out-going interface's IP
|
|
||||||
cc, err := lc.ListenPacket(ctx, "udp", laddr.String())
|
cc, err := lc.ListenPacket(ctx, "udp", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
reply := gosocks5.NewReply(gosocks5.Failure, nil)
|
reply := gosocks5.NewReply(gosocks5.Failure, nil)
|
||||||
@@ -56,6 +57,12 @@ func (h *socks5Handler) handleUDP(ctx context.Context, conn net.Conn, ro *xrecor
|
|||||||
|
|
||||||
saddr := gosocks5.Addr{}
|
saddr := gosocks5.Addr{}
|
||||||
saddr.ParseFrom(cc.LocalAddr().String())
|
saddr.ParseFrom(cc.LocalAddr().String())
|
||||||
|
|
||||||
|
saddr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String())
|
||||||
|
if v := net.ParseIP(h.md.publicAddr); v != nil {
|
||||||
|
saddr.Host = h.md.publicAddr
|
||||||
|
}
|
||||||
|
saddr.Type = 0
|
||||||
reply := gosocks5.NewReply(gosocks5.Succeeded, &saddr)
|
reply := gosocks5.NewReply(gosocks5.Succeeded, &saddr)
|
||||||
log.Trace(reply)
|
log.Trace(reply)
|
||||||
if err := reply.Write(conn); err != nil {
|
if err := reply.Write(conn); err != nil {
|
||||||
@@ -81,16 +88,17 @@ func (h *socks5Handler) handleUDP(ctx context.Context, conn net.Conn, ro *xrecor
|
|||||||
log.Error(err)
|
log.Error(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
pc = metrics.WrapPacketConn(ro.Service, pc)
|
||||||
pStats := xstats.Stats{}
|
|
||||||
cc = stats_wrapper.WrapPacketConn(cc, &pStats)
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
ro.InputBytes = pStats.Get(stats.KindInputBytes)
|
|
||||||
ro.OutputBytes = pStats.Get(stats.KindOutputBytes)
|
|
||||||
}()
|
|
||||||
|
|
||||||
{
|
{
|
||||||
|
pStats := xstats.Stats{}
|
||||||
|
cc = stats_wrapper.WrapPacketConn(cc, &pStats)
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
ro.InputBytes = pStats.Get(stats.KindInputBytes)
|
||||||
|
ro.OutputBytes = pStats.Get(stats.KindOutputBytes)
|
||||||
|
}()
|
||||||
|
|
||||||
clientID := ctxvalue.ClientIDFromContext(ctx)
|
clientID := ctxvalue.ClientIDFromContext(ctx)
|
||||||
cc = traffic_wrapper.WrapPacketConn(
|
cc = traffic_wrapper.WrapPacketConn(
|
||||||
cc,
|
cc,
|
||||||
|
|||||||
@@ -186,10 +186,20 @@ func (h *tunnelHandler) initEntrypoint() (err error) {
|
|||||||
|
|
||||||
func (h *tunnelHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler.HandleOption) (err error) {
|
func (h *tunnelHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler.HandleOption) (err error) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
|
clientIP := conn.RemoteAddr().String()
|
||||||
|
if clientAddr := ctxvalue.ClientAddrFromContext(ctx); clientAddr != "" {
|
||||||
|
clientIP = string(clientAddr)
|
||||||
|
}
|
||||||
|
if h, _, _ := net.SplitHostPort(clientIP); h != "" {
|
||||||
|
clientIP = h
|
||||||
|
}
|
||||||
|
|
||||||
log := h.log.WithFields(map[string]any{
|
log := h.log.WithFields(map[string]any{
|
||||||
"remote": conn.RemoteAddr().String(),
|
"remote": conn.RemoteAddr().String(),
|
||||||
"local": conn.LocalAddr().String(),
|
"local": conn.LocalAddr().String(),
|
||||||
"sid": ctxvalue.SidFromContext(ctx),
|
"sid": ctxvalue.SidFromContext(ctx),
|
||||||
|
"client": clientIP,
|
||||||
})
|
})
|
||||||
|
|
||||||
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
|
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
|
||||||
|
|||||||
@@ -8,8 +8,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type conn struct {
|
type conn struct {
|
||||||
session *wt.Session
|
session *wt.Session
|
||||||
stream *wt.Stream
|
stream *wt.Stream
|
||||||
|
clientAddr net.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
func Conn(session *wt.Session, stream *wt.Stream) net.Conn {
|
func Conn(session *wt.Session, stream *wt.Stream) net.Conn {
|
||||||
@@ -19,6 +20,14 @@ func Conn(session *wt.Session, stream *wt.Stream) net.Conn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ConnWithClientAddr(session *wt.Session, stream *wt.Stream, clientAddr net.Addr) net.Conn {
|
||||||
|
return &conn{
|
||||||
|
session: session,
|
||||||
|
stream: stream,
|
||||||
|
clientAddr: clientAddr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *conn) Read(b []byte) (n int, err error) {
|
func (c *conn) Read(b []byte) (n int, err error) {
|
||||||
return c.stream.Read(b)
|
return c.stream.Read(b)
|
||||||
}
|
}
|
||||||
@@ -39,6 +48,10 @@ func (c *conn) RemoteAddr() net.Addr {
|
|||||||
return c.session.RemoteAddr()
|
return c.session.RemoteAddr()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *conn) ClientAddr() net.Addr {
|
||||||
|
return c.clientAddr
|
||||||
|
}
|
||||||
|
|
||||||
func (c *conn) SetDeadline(t time.Time) error {
|
func (c *conn) SetDeadline(t time.Time) error {
|
||||||
return c.stream.SetDeadline(t)
|
return c.stream.SetDeadline(t)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,6 +106,13 @@ func (c *limitConn) Metadata() metadata.Metadata {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *limitConn) ClientAddr() net.Addr {
|
||||||
|
if sc, ok := c.Conn.(xnet.ClientAddr); ok {
|
||||||
|
return sc.ClientAddr()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type packetConn struct {
|
type packetConn struct {
|
||||||
net.PacketConn
|
net.PacketConn
|
||||||
limiter traffic.TrafficLimiter
|
limiter traffic.TrafficLimiter
|
||||||
|
|||||||
@@ -4,10 +4,12 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-gost/core/logger"
|
"github.com/go-gost/core/logger"
|
||||||
pb "github.com/go-gost/x/internal/util/grpc/proto"
|
pb "github.com/go-gost/x/internal/util/grpc/proto"
|
||||||
|
mdata "google.golang.org/grpc/metadata"
|
||||||
"google.golang.org/grpc/peer"
|
"google.golang.org/grpc/peer"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -28,6 +30,11 @@ func (s *server) Tunnel(srv pb.GostTunel_TunnelServer) error {
|
|||||||
if p, ok := peer.FromContext(srv.Context()); ok {
|
if p, ok := peer.FromContext(srv.Context()); ok {
|
||||||
c.remoteAddr = p.Addr
|
c.remoteAddr = p.Addr
|
||||||
}
|
}
|
||||||
|
if md, ok := mdata.FromIncomingContext(srv.Context()); ok {
|
||||||
|
if cip := getClientIP(md); cip != nil {
|
||||||
|
c.clientAddr = &net.IPAddr{IP: cip}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case s.cqueue <- c:
|
case s.cqueue <- c:
|
||||||
@@ -41,11 +48,39 @@ func (s *server) Tunnel(srv pb.GostTunel_TunnelServer) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getClientIP(md mdata.MD) net.IP {
|
||||||
|
if md == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var cip string
|
||||||
|
// cloudflare CDN
|
||||||
|
if v := md.Get("CF-Connecting-IP"); len(v) > 0 {
|
||||||
|
cip = v[0]
|
||||||
|
}
|
||||||
|
if cip == "" {
|
||||||
|
if v := md.Get("X-Forwarded-For"); len(v) > 0 {
|
||||||
|
ss := strings.Split(v[0], ",")
|
||||||
|
if len(ss) > 0 && ss[0] != "" {
|
||||||
|
cip = ss[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if cip == "" {
|
||||||
|
if v := md.Get("X-Real-Ip"); len(v) > 0 {
|
||||||
|
cip = v[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return net.ParseIP(cip)
|
||||||
|
}
|
||||||
|
|
||||||
type conn struct {
|
type conn struct {
|
||||||
s pb.GostTunel_TunnelServer
|
s pb.GostTunel_TunnelServer
|
||||||
rb []byte
|
rb []byte
|
||||||
localAddr net.Addr
|
localAddr net.Addr
|
||||||
remoteAddr net.Addr
|
remoteAddr net.Addr
|
||||||
|
clientAddr net.Addr
|
||||||
closed chan struct{}
|
closed chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,6 +146,10 @@ func (c *conn) RemoteAddr() net.Addr {
|
|||||||
return c.remoteAddr
|
return c.remoteAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *conn) ClientAddr() net.Addr {
|
||||||
|
return c.clientAddr
|
||||||
|
}
|
||||||
|
|
||||||
func (c *conn) SetDeadline(t time.Time) error {
|
func (c *conn) SetDeadline(t time.Time) error {
|
||||||
return &net.OpError{Op: "set", Net: "grpc", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
|
return &net.OpError{Op: "set", Net: "grpc", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-6
@@ -11,12 +11,13 @@ import (
|
|||||||
|
|
||||||
// a dummy HTTP2 server conn used by HTTP2 handler
|
// a dummy HTTP2 server conn used by HTTP2 handler
|
||||||
type conn struct {
|
type conn struct {
|
||||||
md mdata.Metadata
|
md mdata.Metadata
|
||||||
r *http.Request
|
r *http.Request
|
||||||
w http.ResponseWriter
|
w http.ResponseWriter
|
||||||
laddr net.Addr
|
laddr net.Addr
|
||||||
raddr net.Addr
|
raddr net.Addr
|
||||||
closed chan struct{}
|
clientAddr net.Addr
|
||||||
|
closed chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *conn) Read(b []byte) (n int, err error) {
|
func (c *conn) Read(b []byte) (n int, err error) {
|
||||||
@@ -44,6 +45,10 @@ func (c *conn) RemoteAddr() net.Addr {
|
|||||||
return c.raddr
|
return c.raddr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *conn) ClientAddr() net.Addr {
|
||||||
|
return c.clientAddr
|
||||||
|
}
|
||||||
|
|
||||||
func (c *conn) SetDeadline(t time.Time) error {
|
func (c *conn) SetDeadline(t time.Time) error {
|
||||||
return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
|
return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ type conn struct {
|
|||||||
w io.Writer
|
w io.Writer
|
||||||
remoteAddr net.Addr
|
remoteAddr net.Addr
|
||||||
localAddr net.Addr
|
localAddr net.Addr
|
||||||
|
clientAddr net.Addr
|
||||||
closed chan struct{}
|
closed chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,6 +50,10 @@ func (c *conn) RemoteAddr() net.Addr {
|
|||||||
return c.remoteAddr
|
return c.remoteAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *conn) ClientAddr() net.Addr {
|
||||||
|
return c.clientAddr
|
||||||
|
}
|
||||||
|
|
||||||
func (c *conn) SetDeadline(t time.Time) error {
|
func (c *conn) SetDeadline(t time.Time) error {
|
||||||
return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
|
return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import (
|
|||||||
md "github.com/go-gost/core/metadata"
|
md "github.com/go-gost/core/metadata"
|
||||||
admission "github.com/go-gost/x/admission/wrapper"
|
admission "github.com/go-gost/x/admission/wrapper"
|
||||||
xnet "github.com/go-gost/x/internal/net"
|
xnet "github.com/go-gost/x/internal/net"
|
||||||
|
xhttp "github.com/go-gost/x/internal/net/http"
|
||||||
"github.com/go-gost/x/internal/net/proxyproto"
|
"github.com/go-gost/x/internal/net/proxyproto"
|
||||||
climiter "github.com/go-gost/x/limiter/conn/wrapper"
|
climiter "github.com/go-gost/x/limiter/conn/wrapper"
|
||||||
limiter_wrapper "github.com/go-gost/x/limiter/traffic/wrapper"
|
limiter_wrapper "github.com/go-gost/x/limiter/traffic/wrapper"
|
||||||
@@ -198,11 +199,18 @@ func (l *h2Listener) upgrade(w http.ResponseWriter, r *http.Request) (*conn, err
|
|||||||
Port: 0,
|
Port: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var clientAddr net.Addr
|
||||||
|
if clientIP := xhttp.GetClientIP(r); clientIP != nil {
|
||||||
|
clientAddr = &net.IPAddr{IP: clientIP}
|
||||||
|
}
|
||||||
|
|
||||||
return &conn{
|
return &conn{
|
||||||
r: r.Body,
|
r: r.Body,
|
||||||
w: flushWriter{w},
|
w: flushWriter{w},
|
||||||
localAddr: l.addr,
|
localAddr: l.addr,
|
||||||
remoteAddr: remoteAddr,
|
remoteAddr: remoteAddr,
|
||||||
|
clientAddr: clientAddr,
|
||||||
closed: make(chan struct{}),
|
closed: make(chan struct{}),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
md "github.com/go-gost/core/metadata"
|
md "github.com/go-gost/core/metadata"
|
||||||
admission "github.com/go-gost/x/admission/wrapper"
|
admission "github.com/go-gost/x/admission/wrapper"
|
||||||
xnet "github.com/go-gost/x/internal/net"
|
xnet "github.com/go-gost/x/internal/net"
|
||||||
|
xhttp "github.com/go-gost/x/internal/net/http"
|
||||||
"github.com/go-gost/x/internal/net/proxyproto"
|
"github.com/go-gost/x/internal/net/proxyproto"
|
||||||
climiter "github.com/go-gost/x/limiter/conn/wrapper"
|
climiter "github.com/go-gost/x/limiter/conn/wrapper"
|
||||||
limiter_wrapper "github.com/go-gost/x/limiter/traffic/wrapper"
|
limiter_wrapper "github.com/go-gost/x/limiter/traffic/wrapper"
|
||||||
@@ -148,6 +149,11 @@ func (l *http2Listener) handleFunc(w http.ResponseWriter, r *http.Request) {
|
|||||||
"w": w,
|
"w": w,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if clientIP := xhttp.GetClientIP(r); clientIP != nil {
|
||||||
|
conn.clientAddr = &net.IPAddr{IP: clientIP}
|
||||||
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case l.cqueue <- conn:
|
case l.cqueue <- conn:
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package http3
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
mdata "github.com/go-gost/core/metadata"
|
mdata "github.com/go-gost/core/metadata"
|
||||||
@@ -11,12 +10,11 @@ import (
|
|||||||
|
|
||||||
// a dummy HTTP3 server conn used by HTTP3 handler
|
// a dummy HTTP3 server conn used by HTTP3 handler
|
||||||
type conn struct {
|
type conn struct {
|
||||||
md mdata.Metadata
|
md mdata.Metadata
|
||||||
r *http.Request
|
laddr net.Addr
|
||||||
w http.ResponseWriter
|
raddr net.Addr
|
||||||
laddr net.Addr
|
clientAddr net.Addr
|
||||||
raddr net.Addr
|
closed chan struct{}
|
||||||
closed chan struct{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *conn) Read(b []byte) (n int, err error) {
|
func (c *conn) Read(b []byte) (n int, err error) {
|
||||||
@@ -44,6 +42,10 @@ func (c *conn) RemoteAddr() net.Addr {
|
|||||||
return c.raddr
|
return c.raddr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *conn) ClientAddr() net.Addr {
|
||||||
|
return c.clientAddr
|
||||||
|
}
|
||||||
|
|
||||||
func (c *conn) SetDeadline(t time.Time) error {
|
func (c *conn) SetDeadline(t time.Time) error {
|
||||||
return &net.OpError{Op: "set", Net: "http3", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
|
return &net.OpError{Op: "set", Net: "http3", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/go-gost/core/logger"
|
"github.com/go-gost/core/logger"
|
||||||
md "github.com/go-gost/core/metadata"
|
md "github.com/go-gost/core/metadata"
|
||||||
xnet "github.com/go-gost/x/internal/net"
|
xnet "github.com/go-gost/x/internal/net"
|
||||||
|
xhttp "github.com/go-gost/x/internal/net/http"
|
||||||
mdx "github.com/go-gost/x/metadata"
|
mdx "github.com/go-gost/x/metadata"
|
||||||
"github.com/go-gost/x/registry"
|
"github.com/go-gost/x/registry"
|
||||||
"github.com/quic-go/quic-go"
|
"github.com/quic-go/quic-go"
|
||||||
@@ -134,6 +135,11 @@ func (l *http3Listener) handleFunc(w http.ResponseWriter, r *http.Request) {
|
|||||||
"w": w,
|
"w": w,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if clientIP := xhttp.GetClientIP(r); clientIP != nil {
|
||||||
|
conn.clientAddr = &net.IPAddr{IP: clientIP}
|
||||||
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case l.cqueue <- conn:
|
case l.cqueue <- conn:
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
md "github.com/go-gost/core/metadata"
|
md "github.com/go-gost/core/metadata"
|
||||||
admission "github.com/go-gost/x/admission/wrapper"
|
admission "github.com/go-gost/x/admission/wrapper"
|
||||||
xnet "github.com/go-gost/x/internal/net"
|
xnet "github.com/go-gost/x/internal/net"
|
||||||
|
xhttp "github.com/go-gost/x/internal/net/http"
|
||||||
wt_util "github.com/go-gost/x/internal/util/wt"
|
wt_util "github.com/go-gost/x/internal/util/wt"
|
||||||
traffic_limiter "github.com/go-gost/x/limiter/traffic"
|
traffic_limiter "github.com/go-gost/x/limiter/traffic"
|
||||||
limiter_wrapper "github.com/go-gost/x/limiter/traffic/wrapper"
|
limiter_wrapper "github.com/go-gost/x/limiter/traffic/wrapper"
|
||||||
@@ -153,9 +154,15 @@ func (l *wtListener) Close() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *wtListener) upgrade(w http.ResponseWriter, r *http.Request) {
|
func (l *wtListener) upgrade(w http.ResponseWriter, r *http.Request) {
|
||||||
|
clientIP := xhttp.GetClientIP(r)
|
||||||
|
cip := ""
|
||||||
|
if clientIP != nil {
|
||||||
|
cip = clientIP.String()
|
||||||
|
}
|
||||||
log := l.logger.WithFields(map[string]any{
|
log := l.logger.WithFields(map[string]any{
|
||||||
"local": l.addr.String(),
|
"local": l.addr.String(),
|
||||||
"remote": r.RemoteAddr,
|
"remote": r.RemoteAddr,
|
||||||
|
"client": cip,
|
||||||
})
|
})
|
||||||
if l.logger.IsLevelEnabled(logger.TraceLevel) {
|
if l.logger.IsLevelEnabled(logger.TraceLevel) {
|
||||||
dump, _ := httputil.DumpRequest(r, false)
|
dump, _ := httputil.DumpRequest(r, false)
|
||||||
@@ -169,10 +176,15 @@ func (l *wtListener) upgrade(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
l.mux(s, log)
|
var clientAddr net.Addr
|
||||||
|
if clientIP != nil {
|
||||||
|
clientAddr = &net.IPAddr{IP: clientIP}
|
||||||
|
}
|
||||||
|
|
||||||
|
l.mux(s, clientAddr, log)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *wtListener) mux(s *wt.Session, log logger.Logger) (err error) {
|
func (l *wtListener) mux(s *wt.Session, clientAddr net.Addr, log logger.Logger) (err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.CloseWithError(1, err.Error())
|
s.CloseWithError(1, err.Error())
|
||||||
@@ -190,7 +202,7 @@ func (l *wtListener) mux(s *wt.Session, log logger.Logger) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case l.cqueue <- wt_util.Conn(s, stream):
|
case l.cqueue <- wt_util.ConnWithClientAddr(s, stream, clientAddr):
|
||||||
default:
|
default:
|
||||||
stream.Close()
|
stream.Close()
|
||||||
l.logger.Warnf("connection queue is full, stream %v discarded", stream.StreamID())
|
l.logger.Warnf("connection queue is full, stream %v discarded", stream.StreamID())
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
md "github.com/go-gost/core/metadata"
|
md "github.com/go-gost/core/metadata"
|
||||||
admission "github.com/go-gost/x/admission/wrapper"
|
admission "github.com/go-gost/x/admission/wrapper"
|
||||||
xnet "github.com/go-gost/x/internal/net"
|
xnet "github.com/go-gost/x/internal/net"
|
||||||
|
xhttp "github.com/go-gost/x/internal/net/http"
|
||||||
"github.com/go-gost/x/internal/net/proxyproto"
|
"github.com/go-gost/x/internal/net/proxyproto"
|
||||||
"github.com/go-gost/x/internal/util/mux"
|
"github.com/go-gost/x/internal/util/mux"
|
||||||
ws_util "github.com/go-gost/x/internal/util/ws"
|
ws_util "github.com/go-gost/x/internal/util/ws"
|
||||||
@@ -162,26 +163,36 @@ func (l *mwsListener) Addr() net.Addr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *mwsListener) upgrade(w http.ResponseWriter, r *http.Request) {
|
func (l *mwsListener) upgrade(w http.ResponseWriter, r *http.Request) {
|
||||||
|
clientIP := xhttp.GetClientIP(r)
|
||||||
|
cip := ""
|
||||||
|
if clientIP != nil {
|
||||||
|
cip = clientIP.String()
|
||||||
|
}
|
||||||
log := l.logger.WithFields(map[string]any{
|
log := l.logger.WithFields(map[string]any{
|
||||||
"local": l.addr.String(),
|
"local": l.addr.String(),
|
||||||
"remote": r.RemoteAddr,
|
"remote": r.RemoteAddr,
|
||||||
|
"client": cip,
|
||||||
})
|
})
|
||||||
if l.logger.IsLevelEnabled(logger.TraceLevel) {
|
if log.IsLevelEnabled(logger.TraceLevel) {
|
||||||
dump, _ := httputil.DumpRequest(r, false)
|
dump, _ := httputil.DumpRequest(r, false)
|
||||||
log.Trace(string(dump))
|
log.Trace(string(dump))
|
||||||
}
|
}
|
||||||
|
|
||||||
conn, err := l.upgrader.Upgrade(w, r, l.md.header)
|
conn, err := l.upgrader.Upgrade(w, r, l.md.header)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
l.mux(ws_util.Conn(conn), log)
|
var clientAddr net.Addr
|
||||||
|
if clientIP != nil {
|
||||||
|
clientAddr = &net.IPAddr{IP: clientIP}
|
||||||
|
}
|
||||||
|
|
||||||
|
l.mux(ws_util.Conn(conn), clientAddr, log)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *mwsListener) mux(conn net.Conn, log logger.Logger) {
|
func (l *mwsListener) mux(conn net.Conn, clientAddr net.Addr, log logger.Logger) {
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
session, err := mux.ServerSession(conn, l.md.muxCfg)
|
session, err := mux.ServerSession(conn, l.md.muxCfg)
|
||||||
@@ -199,10 +210,19 @@ func (l *mwsListener) mux(conn net.Conn, log logger.Logger) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case l.cqueue <- stream:
|
case l.cqueue <- &connWithClientAddr{Conn: stream, clientAddr: clientAddr}:
|
||||||
default:
|
default:
|
||||||
stream.Close()
|
stream.Close()
|
||||||
log.Warnf("connection queue is full, client %s discarded", stream.RemoteAddr())
|
log.Warnf("connection queue is full, client %s discarded", stream.RemoteAddr())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type connWithClientAddr struct {
|
||||||
|
net.Conn
|
||||||
|
clientAddr net.Addr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *connWithClientAddr) ClientAddr() net.Addr {
|
||||||
|
return c.clientAddr
|
||||||
|
}
|
||||||
|
|||||||
+12
-13
@@ -159,24 +159,23 @@ func (l *wsListener) Addr() net.Addr {
|
|||||||
|
|
||||||
func (l *wsListener) upgrade(w http.ResponseWriter, r *http.Request) {
|
func (l *wsListener) upgrade(w http.ResponseWriter, r *http.Request) {
|
||||||
clientIP := xhttp.GetClientIP(r)
|
clientIP := xhttp.GetClientIP(r)
|
||||||
if l.logger.IsLevelEnabled(logger.TraceLevel) {
|
cip := ""
|
||||||
sip := ""
|
if clientIP != nil {
|
||||||
if clientIP != nil {
|
cip = clientIP.String()
|
||||||
sip = clientIP.String()
|
}
|
||||||
}
|
log := l.logger.WithFields(map[string]any{
|
||||||
log := l.logger.WithFields(map[string]any{
|
"local": l.addr.String(),
|
||||||
"local": l.addr.String(),
|
"remote": r.RemoteAddr,
|
||||||
"remote": r.RemoteAddr,
|
"client": cip,
|
||||||
"clientIP": sip,
|
})
|
||||||
})
|
if log.IsLevelEnabled(logger.TraceLevel) {
|
||||||
dump, _ := httputil.DumpRequest(r, false)
|
dump, _ := httputil.DumpRequest(r, false)
|
||||||
log.Trace(string(dump))
|
log.Trace(string(dump))
|
||||||
}
|
}
|
||||||
|
|
||||||
conn, err := l.upgrader.Upgrade(w, r, l.md.header)
|
conn, err := l.upgrader.Upgrade(w, r, l.md.header)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.logger.Error(err)
|
log.Error(err)
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,6 +188,6 @@ func (l *wsListener) upgrade(w http.ResponseWriter, r *http.Request) {
|
|||||||
case l.cqueue <- ws_util.ConnWithClientAddr(conn, clientAddr):
|
case l.cqueue <- ws_util.ConnWithClientAddr(conn, clientAddr):
|
||||||
default:
|
default:
|
||||||
conn.Close()
|
conn.Close()
|
||||||
l.logger.Warnf("connection queue is full, client %s discarded", conn.RemoteAddr())
|
log.Warnf("connection queue is full, client %s discarded", conn.RemoteAddr())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,6 +80,13 @@ func (c *serverConn) Metadata() metadata.Metadata {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *serverConn) ClientAddr() net.Addr {
|
||||||
|
if sc, ok := c.Conn.(xnet.ClientAddr); ok {
|
||||||
|
return sc.ClientAddr()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type packetConn struct {
|
type packetConn struct {
|
||||||
net.PacketConn
|
net.PacketConn
|
||||||
service string
|
service string
|
||||||
|
|||||||
@@ -82,6 +82,13 @@ func (c *conn) Metadata() metadata.Metadata {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *conn) ClientAddr() net.Addr {
|
||||||
|
if sc, ok := c.Conn.(xnet.ClientAddr); ok {
|
||||||
|
return sc.ClientAddr()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type packetConn struct {
|
type packetConn struct {
|
||||||
net.PacketConn
|
net.PacketConn
|
||||||
stats stats.Stats
|
stats stats.Stats
|
||||||
|
|||||||
Reference in New Issue
Block a user