Add max_clients to cap the maximum number of client queries
This commit is contained in:
parent
e272dd84f7
commit
732c451dd4
|
@ -40,6 +40,7 @@ type Config struct {
|
||||||
SourceRequireNoLog bool `toml:"require_nolog"`
|
SourceRequireNoLog bool `toml:"require_nolog"`
|
||||||
SourceIPv4 bool `toml:"ipv4_servers"`
|
SourceIPv4 bool `toml:"ipv4_servers"`
|
||||||
SourceIPv6 bool `toml:"ipv6_servers"`
|
SourceIPv6 bool `toml:"ipv6_servers"`
|
||||||
|
MaxClients uint32 `toml:"max_clients"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func newConfig() Config {
|
func newConfig() Config {
|
||||||
|
@ -57,6 +58,7 @@ func newConfig() Config {
|
||||||
SourceRequireNoLog: true,
|
SourceRequireNoLog: true,
|
||||||
SourceIPv4: true,
|
SourceIPv4: true,
|
||||||
SourceIPv6: false,
|
SourceIPv6: false,
|
||||||
|
MaxClients: 100,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,6 +130,7 @@ func ConfigLoad(proxy *Proxy, svcFlag *string, config_file string) error {
|
||||||
dlog.UseLogFile(*config.LogFile)
|
dlog.UseLogFile(*config.LogFile)
|
||||||
}
|
}
|
||||||
proxy.timeout = time.Duration(config.Timeout) * time.Millisecond
|
proxy.timeout = time.Duration(config.Timeout) * time.Millisecond
|
||||||
|
proxy.maxClients = config.MaxClients
|
||||||
proxy.mainProto = "udp"
|
proxy.mainProto = "udp"
|
||||||
if config.ForceTCP {
|
if config.ForceTCP {
|
||||||
proxy.mainProto = "tcp"
|
proxy.mainProto = "tcp"
|
||||||
|
|
|
@ -23,6 +23,11 @@
|
||||||
listen_addresses = ['127.0.0.1:53', '[::1]:53']
|
listen_addresses = ['127.0.0.1:53', '[::1]:53']
|
||||||
|
|
||||||
|
|
||||||
|
## Maximum number of simultaneous client connections to accept
|
||||||
|
|
||||||
|
max_clients = 100
|
||||||
|
|
||||||
|
|
||||||
## Require servers (from static definitions and from remote sources) to satisfy specific properties
|
## Require servers (from static definitions and from remote sources) to satisfy specific properties
|
||||||
|
|
||||||
# Use servers reachable over IPv4
|
# Use servers reachable over IPv4
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jedisct1/dlog"
|
"github.com/jedisct1/dlog"
|
||||||
|
@ -50,6 +51,8 @@ type Proxy struct {
|
||||||
forwardFile string
|
forwardFile string
|
||||||
pluginsGlobals PluginsGlobals
|
pluginsGlobals PluginsGlobals
|
||||||
urlsToPrefetch []URLToPrefetch
|
urlsToPrefetch []URLToPrefetch
|
||||||
|
clientsCount uint32
|
||||||
|
maxClients uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
type App struct {
|
type App struct {
|
||||||
|
@ -218,6 +221,11 @@ func (proxy *Proxy) udpListener(clientPc *net.UDPConn) {
|
||||||
}
|
}
|
||||||
packet := buffer[:length]
|
packet := buffer[:length]
|
||||||
go func() {
|
go func() {
|
||||||
|
if !proxy.clientsCountInc() {
|
||||||
|
dlog.Warnf("Too many connections (max=%d)", proxy.maxClients)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer proxy.clientsCountDec()
|
||||||
proxy.processIncomingQuery(proxy.serversInfo.getOne(), "udp", proxy.mainProto, packet, &clientAddr, clientPc)
|
proxy.processIncomingQuery(proxy.serversInfo.getOne(), "udp", proxy.mainProto, packet, &clientAddr, clientPc)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
@ -242,6 +250,11 @@ func (proxy *Proxy) tcpListener(acceptPc *net.TCPListener) {
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
defer clientPc.Close()
|
defer clientPc.Close()
|
||||||
|
if !proxy.clientsCountInc() {
|
||||||
|
dlog.Warnf("Too many connections (max=%d)", proxy.maxClients)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer proxy.clientsCountDec()
|
||||||
clientPc.SetDeadline(time.Now().Add(proxy.timeout))
|
clientPc.SetDeadline(time.Now().Add(proxy.timeout))
|
||||||
packet, err := ReadPrefixed(clientPc.(*net.TCPConn))
|
packet, err := ReadPrefixed(clientPc.(*net.TCPConn))
|
||||||
if err != nil || len(packet) < MinDNSPacketSize {
|
if err != nil || len(packet) < MinDNSPacketSize {
|
||||||
|
@ -300,6 +313,26 @@ func (proxy *Proxy) exchangeWithTCPServer(serverInfo *ServerInfo, encryptedQuery
|
||||||
return proxy.Decrypt(serverInfo, encryptedResponse, clientNonce)
|
return proxy.Decrypt(serverInfo, encryptedResponse, clientNonce)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (proxy *Proxy) clientsCountInc() bool {
|
||||||
|
for {
|
||||||
|
count := proxy.clientsCount
|
||||||
|
if count >= proxy.maxClients {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if atomic.CompareAndSwapUint32(&proxy.clientsCount, count, count+1) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (proxy *Proxy) clientsCountDec() {
|
||||||
|
for {
|
||||||
|
if count := proxy.clientsCount; count == 0 || atomic.CompareAndSwapUint32(&proxy.clientsCount, count, count-1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (proxy *Proxy) processIncomingQuery(serverInfo *ServerInfo, clientProto string, serverProto string, query []byte, clientAddr *net.Addr, clientPc net.Conn) {
|
func (proxy *Proxy) processIncomingQuery(serverInfo *ServerInfo, clientProto string, serverProto string, query []byte, clientAddr *net.Addr, clientPc net.Conn) {
|
||||||
if len(query) < MinDNSPacketSize || serverInfo == nil {
|
if len(query) < MinDNSPacketSize || serverInfo == nil {
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in New Issue