mirror of
https://github.com/XTLS/Xray-core.git
synced 2024-11-22 12:49:20 +02:00
Add UDPFilter to Socks5 server when `auth == password` (#3371)
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
This commit is contained in:
parent
544f7661ca
commit
9ee9a0634e
|
@ -27,6 +27,7 @@ type Server struct {
|
||||||
config *ServerConfig
|
config *ServerConfig
|
||||||
policyManager policy.Manager
|
policyManager policy.Manager
|
||||||
cone bool
|
cone bool
|
||||||
|
udpFilter *UDPFilter
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServer creates a new Server object.
|
// NewServer creates a new Server object.
|
||||||
|
@ -37,6 +38,9 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
|
||||||
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||||
cone: ctx.Value("cone").(bool),
|
cone: ctx.Value("cone").(bool),
|
||||||
}
|
}
|
||||||
|
if config.AuthType == AuthType_PASSWORD {
|
||||||
|
s.udpFilter = new(UDPFilter) // We only use this when auth is enabled
|
||||||
|
}
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,6 +139,9 @@ func (s *Server) processTCP(ctx context.Context, conn stat.Connection, dispatche
|
||||||
}
|
}
|
||||||
|
|
||||||
if request.Command == protocol.RequestCommandUDP {
|
if request.Command == protocol.RequestCommandUDP {
|
||||||
|
if s.udpFilter != nil {
|
||||||
|
s.udpFilter.Add(conn.RemoteAddr())
|
||||||
|
}
|
||||||
return s.handleUDP(conn)
|
return s.handleUDP(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,6 +200,10 @@ func (s *Server) transport(ctx context.Context, reader io.Reader, writer io.Writ
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) handleUDPPayload(ctx context.Context, conn stat.Connection, dispatcher routing.Dispatcher) error {
|
func (s *Server) handleUDPPayload(ctx context.Context, conn stat.Connection, dispatcher routing.Dispatcher) error {
|
||||||
|
if s.udpFilter != nil && !s.udpFilter.Check(conn.RemoteAddr()) {
|
||||||
|
newError("Unauthorized UDP access from ", conn.RemoteAddr().String()).AtDebug().WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
udpServer := udp.NewDispatcher(dispatcher, func(ctx context.Context, packet *udp_proto.Packet) {
|
udpServer := udp.NewDispatcher(dispatcher, func(ctx context.Context, packet *udp_proto.Packet) {
|
||||||
payload := packet.Payload
|
payload := packet.Payload
|
||||||
newError("writing back UDP response with ", payload.Len(), " bytes").AtDebug().WriteToLog(session.ExportIDToError(ctx))
|
newError("writing back UDP response with ", payload.Len(), " bytes").AtDebug().WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package socks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
In the sock implementation of * ray, UDP authentication is flawed and can be bypassed.
|
||||||
|
Tracking a UDP connection may be a bit troublesome.
|
||||||
|
Here is a simple solution.
|
||||||
|
We creat a filter, add remote IP to the pool when it try to establish a UDP connection with auth.
|
||||||
|
And drop UDP packets from unauthorized IP.
|
||||||
|
After discussion, we believe it is not necessary to add a timeout mechanism to this filter.
|
||||||
|
*/
|
||||||
|
|
||||||
|
type UDPFilter struct {
|
||||||
|
ips sync.Map
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *UDPFilter) Add(addr net.Addr) bool {
|
||||||
|
ip, _, _ := net.SplitHostPort(addr.String())
|
||||||
|
f.ips.Store(ip, true)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *UDPFilter) Check(addr net.Addr) bool {
|
||||||
|
ip, _, _ := net.SplitHostPort(addr.String())
|
||||||
|
_, ok := f.ips.Load(ip)
|
||||||
|
return ok
|
||||||
|
}
|
Loading…
Reference in New Issue