!feat(vless): IP restriction

Beta, only works for vless for now and it's not perfect needs a lot of testing.
This commit is contained in:
Devman 2023-06-30 13:13:36 +00:00
parent 34b68518fd
commit 3d692eb208
9 changed files with 94 additions and 22 deletions

View file

@ -42,6 +42,7 @@ type tcpWorker struct {
sniffingConfig *proxyman.SniffingConfig
uplinkCounter stats.Counter
downlinkCounter stats.Counter
ipLimitPool map[session.ID]*stat.UserIpRestriction
hub internet.Listener
@ -104,9 +105,18 @@ func (w *tcpWorker) callback(conn stat.Connection) {
}
ctx = session.ContextWithContent(ctx, content)
if err := w.proxy.Process(ctx, net.Network_TCP, conn, w.dispatcher); err != nil {
// Add this IP address to the pool for futher IP limit check
w.ipLimitPool[sid] = &stat.UserIpRestriction{
IpAddress: net.IP(conn.RemoteAddr().Network()),
}
if err := w.proxy.Process(ctx, net.Network_TCP, conn, w.dispatcher, &w.ipLimitPool, w.ipLimitPool[sid]); err != nil {
newError("connection ends").Base(err).WriteToLog(session.ExportIDToError(ctx))
}
// Deletes the IP address from the pool after the connection ends
delete(w.ipLimitPool, sid)
cancel()
conn.Close()
}
@ -116,6 +126,9 @@ func (w *tcpWorker) Proxy() proxy.Inbound {
}
func (w *tcpWorker) Start() error {
if len(w.ipLimitPool) == 0 {
w.ipLimitPool = make(map[session.ID]*stat.UserIpRestriction)
}
ctx := context.Background()
hub, err := internet.ListenTCP(ctx, w.address, w.port, w.stream, func(conn stat.Connection) {
go w.callback(conn)
@ -244,6 +257,7 @@ type udpWorker struct {
sniffingConfig *proxyman.SniffingConfig
uplinkCounter stats.Counter
downlinkCounter stats.Counter
ipLimitPool map[session.ID]*stat.UserIpRestriction
checker *task.Periodic
activeConn map[connID]*udpConn
@ -326,9 +340,19 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
content.SniffingRequest.RouteOnly = w.sniffingConfig.RouteOnly
}
ctx = session.ContextWithContent(ctx, content)
if err := w.proxy.Process(ctx, net.Network_UDP, conn, w.dispatcher); err != nil {
// Add this IP address to the pool for futher IP limit check
w.ipLimitPool[sid] = &stat.UserIpRestriction{
IpAddress: net.IP(conn.RemoteAddr().Network()),
}
if err := w.proxy.Process(ctx, net.Network_UDP, conn, w.dispatcher, &w.ipLimitPool, w.ipLimitPool[sid]); err != nil {
newError("connection ends").Base(err).WriteToLog(session.ExportIDToError(ctx))
}
// Deletes the IP address from the pool after the connection ends
delete(w.ipLimitPool, sid)
conn.Close()
// conn not removed by checker TODO may be lock worker here is better
if !conn.inactive {
@ -379,6 +403,9 @@ func (w *udpWorker) clean() error {
}
func (w *udpWorker) Start() error {
if len(w.ipLimitPool) == 0 {
w.ipLimitPool = make(map[session.ID]*stat.UserIpRestriction)
}
w.activeConn = make(map[connID]*udpConn, 16)
ctx := context.Background()
h, err := udp.ListenUDP(ctx, w.address, w.port, w.stream, udp.HubCapacity(256))
@ -478,7 +505,7 @@ func (w *dsWorker) callback(conn stat.Connection) {
}
ctx = session.ContextWithContent(ctx, content)
if err := w.proxy.Process(ctx, net.Network_UNIX, conn, w.dispatcher); err != nil {
if err := w.proxy.Process(ctx, net.Network_UNIX, conn, w.dispatcher, nil, nil); err != nil {
newError("connection ends").Base(err).WriteToLog(session.ExportIDToError(ctx))
}
cancel()