+ GET /control/clients/find: add "disallowed" property
This commit is contained in:
parent
07db05dd80
commit
dd3027afe7
|
@ -940,7 +940,7 @@ Error response (Client not found):
|
||||||
### API: Find clients by IP
|
### API: Find clients by IP
|
||||||
|
|
||||||
This method returns the list of clients (manual and auto-clients) matching the IP list.
|
This method returns the list of clients (manual and auto-clients) matching the IP list.
|
||||||
For auto-clients only `name`, `ids` and `whois_info` fields are set. Other fields are empty.
|
For auto-clients only `name`, `ids`, `whois_info`, `disallowed` fields are set. Other fields are empty.
|
||||||
|
|
||||||
Request:
|
Request:
|
||||||
|
|
||||||
|
@ -966,11 +966,18 @@ Response:
|
||||||
key: "value"
|
key: "value"
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"disallowed": "..."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
...
|
...
|
||||||
]
|
]
|
||||||
|
|
||||||
|
`disallowed`:
|
||||||
|
* "": IP is allowed
|
||||||
|
* not "", e.g. "127.0.0.0/24" - IP is disallowed by "disallowed IP list", and the string contains the matched rule (IP or CIDR)
|
||||||
|
* "not-in-allowed-list" - IP is disallowed by "allowed IP list"
|
||||||
|
|
||||||
|
|
||||||
## DNS general settings
|
## DNS general settings
|
||||||
|
|
||||||
|
|
|
@ -80,43 +80,43 @@ func processIPCIDRArray(dst *map[string]bool, dstIPNet *[]net.IPNet, src []strin
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsBlockedIP - return TRUE if this client should be blocked
|
// IsBlockedIP - return TRUE if this client should be blocked
|
||||||
func (a *accessCtx) IsBlockedIP(ip string) bool {
|
func (a *accessCtx) IsBlockedIP(ip string) (bool, string) {
|
||||||
a.lock.Lock()
|
a.lock.Lock()
|
||||||
defer a.lock.Unlock()
|
defer a.lock.Unlock()
|
||||||
|
|
||||||
if len(a.allowedClients) != 0 || len(a.allowedClientsIPNet) != 0 {
|
if len(a.allowedClients) != 0 || len(a.allowedClientsIPNet) != 0 {
|
||||||
_, ok := a.allowedClients[ip]
|
_, ok := a.allowedClients[ip]
|
||||||
if ok {
|
if ok {
|
||||||
return false
|
return false, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(a.allowedClientsIPNet) != 0 {
|
if len(a.allowedClientsIPNet) != 0 {
|
||||||
ipAddr := net.ParseIP(ip)
|
ipAddr := net.ParseIP(ip)
|
||||||
for _, ipnet := range a.allowedClientsIPNet {
|
for _, ipnet := range a.allowedClientsIPNet {
|
||||||
if ipnet.Contains(ipAddr) {
|
if ipnet.Contains(ipAddr) {
|
||||||
return false
|
return false, ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true, "not-in-allowed-list"
|
||||||
}
|
}
|
||||||
|
|
||||||
_, ok := a.disallowedClients[ip]
|
_, ok := a.disallowedClients[ip]
|
||||||
if ok {
|
if ok {
|
||||||
return true
|
return true, ip
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(a.disallowedClientsIPNet) != 0 {
|
if len(a.disallowedClientsIPNet) != 0 {
|
||||||
ipAddr := net.ParseIP(ip)
|
ipAddr := net.ParseIP(ip)
|
||||||
for _, ipnet := range a.disallowedClientsIPNet {
|
for _, ipnet := range a.disallowedClientsIPNet {
|
||||||
if ipnet.Contains(ipAddr) {
|
if ipnet.Contains(ipAddr) {
|
||||||
return true
|
return true, ipnet.String()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsBlockedDomain - return TRUE if this domain should be blocked
|
// IsBlockedDomain - return TRUE if this domain should be blocked
|
||||||
|
|
|
@ -298,3 +298,8 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
p.ServeHTTP(w, r)
|
p.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsBlockedIP - return TRUE if this client should be blocked
|
||||||
|
func (s *Server) IsBlockedIP(ip string) (bool, string) {
|
||||||
|
return s.access.IsBlockedIP(ip)
|
||||||
|
}
|
||||||
|
|
|
@ -878,20 +878,28 @@ func TestIsBlockedIPAllowed(t *testing.T) {
|
||||||
a := &accessCtx{}
|
a := &accessCtx{}
|
||||||
assert.True(t, a.Init([]string{"1.1.1.1", "2.2.0.0/16"}, nil, nil) == nil)
|
assert.True(t, a.Init([]string{"1.1.1.1", "2.2.0.0/16"}, nil, nil) == nil)
|
||||||
|
|
||||||
assert.True(t, !a.IsBlockedIP("1.1.1.1"))
|
disallowed, _ := a.IsBlockedIP("1.1.1.1")
|
||||||
assert.True(t, a.IsBlockedIP("1.1.1.2"))
|
assert.False(t, disallowed)
|
||||||
assert.True(t, !a.IsBlockedIP("2.2.1.1"))
|
disallowed, _ = a.IsBlockedIP("1.1.1.2")
|
||||||
assert.True(t, a.IsBlockedIP("2.3.1.1"))
|
assert.True(t, disallowed)
|
||||||
|
disallowed, _ = a.IsBlockedIP("2.2.1.1")
|
||||||
|
assert.False(t, disallowed)
|
||||||
|
disallowed, _ = a.IsBlockedIP("2.3.1.1")
|
||||||
|
assert.True(t, disallowed)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIsBlockedIPDisallowed(t *testing.T) {
|
func TestIsBlockedIPDisallowed(t *testing.T) {
|
||||||
a := &accessCtx{}
|
a := &accessCtx{}
|
||||||
assert.True(t, a.Init(nil, []string{"1.1.1.1", "2.2.0.0/16"}, nil) == nil)
|
assert.True(t, a.Init(nil, []string{"1.1.1.1", "2.2.0.0/16"}, nil) == nil)
|
||||||
|
|
||||||
assert.True(t, a.IsBlockedIP("1.1.1.1"))
|
disallowed, _ := a.IsBlockedIP("1.1.1.1")
|
||||||
assert.True(t, !a.IsBlockedIP("1.1.1.2"))
|
assert.True(t, disallowed)
|
||||||
assert.True(t, a.IsBlockedIP("2.2.1.1"))
|
disallowed, _ = a.IsBlockedIP("1.1.1.2")
|
||||||
assert.True(t, !a.IsBlockedIP("2.3.1.1"))
|
assert.False(t, disallowed)
|
||||||
|
disallowed, _ = a.IsBlockedIP("2.2.1.1")
|
||||||
|
assert.True(t, disallowed)
|
||||||
|
disallowed, _ = a.IsBlockedIP("2.3.1.1")
|
||||||
|
assert.False(t, disallowed)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIsBlockedIPBlockedDomain(t *testing.T) {
|
func TestIsBlockedIPBlockedDomain(t *testing.T) {
|
||||||
|
|
|
@ -12,7 +12,8 @@ import (
|
||||||
|
|
||||||
func (s *Server) beforeRequestHandler(_ *proxy.Proxy, d *proxy.DNSContext) (bool, error) {
|
func (s *Server) beforeRequestHandler(_ *proxy.Proxy, d *proxy.DNSContext) (bool, error) {
|
||||||
ip := ipFromAddr(d.Addr)
|
ip := ipFromAddr(d.Addr)
|
||||||
if s.access.IsBlockedIP(ip) {
|
disallowed, _ := s.access.IsBlockedIP(ip)
|
||||||
|
if disallowed {
|
||||||
log.Tracef("Client IP %s is blocked by settings", ip)
|
log.Tracef("Client IP %s is blocked by settings", ip)
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,6 +80,8 @@ type clientsContainer struct {
|
||||||
// dhcpServer is used for looking up clients IP addresses by MAC addresses
|
// dhcpServer is used for looking up clients IP addresses by MAC addresses
|
||||||
dhcpServer *dhcpd.Server
|
dhcpServer *dhcpd.Server
|
||||||
|
|
||||||
|
DNSServer *dnsforward.Server
|
||||||
|
|
||||||
autoHosts *util.AutoHosts // get entries from system hosts-files
|
autoHosts *util.AutoHosts // get entries from system hosts-files
|
||||||
|
|
||||||
testing bool // if TRUE, this object is used for internal tests
|
testing bool // if TRUE, this object is used for internal tests
|
||||||
|
|
|
@ -21,6 +21,13 @@ type clientJSON struct {
|
||||||
BlockedServices []string `json:"blocked_services"`
|
BlockedServices []string `json:"blocked_services"`
|
||||||
|
|
||||||
Upstreams []string `json:"upstreams"`
|
Upstreams []string `json:"upstreams"`
|
||||||
|
|
||||||
|
WhoisInfo map[string]interface{} `json:"whois_info"`
|
||||||
|
|
||||||
|
// * "": IP is allowed
|
||||||
|
// * not "", e.g. "127.0.0.0/24" - IP is disallowed by "disallowed IP list", and the string contains the matched rule (IP or CIDR)
|
||||||
|
// * "not-in-allowed-list" - IP is disallowed by "allowed IP list"
|
||||||
|
Disallowed string `json:"disallowed"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type clientHostJSON struct {
|
type clientHostJSON struct {
|
||||||
|
@ -123,15 +130,9 @@ func clientToJSON(c *Client) clientJSON {
|
||||||
return cj
|
return cj
|
||||||
}
|
}
|
||||||
|
|
||||||
type clientHostJSONWithID struct {
|
|
||||||
IDs []string `json:"ids"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
WhoisInfo map[string]interface{} `json:"whois_info"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert ClientHost object to JSON
|
// Convert ClientHost object to JSON
|
||||||
func clientHostToJSON(ip string, ch ClientHost) clientHostJSONWithID {
|
func clientHostToJSON(ip string, ch ClientHost) clientJSON {
|
||||||
cj := clientHostJSONWithID{
|
cj := clientJSON{
|
||||||
Name: ch.Host,
|
Name: ch.Host,
|
||||||
IDs: []string{ip},
|
IDs: []string{ip},
|
||||||
}
|
}
|
||||||
|
@ -255,9 +256,21 @@ func (clients *clientsContainer) handleFindClient(w http.ResponseWriter, r *http
|
||||||
continue // a client with this IP isn't found
|
continue // a client with this IP isn't found
|
||||||
}
|
}
|
||||||
cj := clientHostToJSON(ip, ch)
|
cj := clientHostToJSON(ip, ch)
|
||||||
|
|
||||||
|
disallowed, disallowedRule := clients.DNSServer.IsBlockedIP(ip)
|
||||||
|
if disallowed {
|
||||||
|
cj.Disallowed = disallowedRule
|
||||||
|
}
|
||||||
|
|
||||||
el[ip] = cj
|
el[ip] = cj
|
||||||
} else {
|
} else {
|
||||||
cj := clientToJSON(&c)
|
cj := clientToJSON(&c)
|
||||||
|
|
||||||
|
disallowed, disallowedRule := clients.DNSServer.IsBlockedIP(ip)
|
||||||
|
if disallowed {
|
||||||
|
cj.Disallowed = disallowedRule
|
||||||
|
}
|
||||||
|
|
||||||
el[ip] = cj
|
el[ip] = cj
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,7 @@ func initDNSServer() error {
|
||||||
p.DHCPServer = Context.dhcpServer
|
p.DHCPServer = Context.dhcpServer
|
||||||
}
|
}
|
||||||
Context.dnsServer = dnsforward.NewServer(p)
|
Context.dnsServer = dnsforward.NewServer(p)
|
||||||
|
Context.clients.DNSServer = Context.dnsServer
|
||||||
dnsConfig := generateServerConfig()
|
dnsConfig := generateServerConfig()
|
||||||
err = Context.dnsServer.Prepare(&dnsConfig)
|
err = Context.dnsServer.Prepare(&dnsConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -1757,7 +1757,57 @@ components:
|
||||||
properties:
|
properties:
|
||||||
1.2.3.4:
|
1.2.3.4:
|
||||||
items:
|
items:
|
||||||
$ref: "#/components/schemas/Client"
|
$ref: "#/components/schemas/ClientFindSubEntry"
|
||||||
|
|
||||||
|
ClientFindSubEntry:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: Name
|
||||||
|
example: localhost
|
||||||
|
ids:
|
||||||
|
type: array
|
||||||
|
description: IP, CIDR or MAC address
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
use_global_settings:
|
||||||
|
type: boolean
|
||||||
|
filtering_enabled:
|
||||||
|
type: boolean
|
||||||
|
parental_enabled:
|
||||||
|
type: boolean
|
||||||
|
safebrowsing_enabled:
|
||||||
|
type: boolean
|
||||||
|
safesearch_enabled:
|
||||||
|
type: boolean
|
||||||
|
use_global_blocked_services:
|
||||||
|
type: boolean
|
||||||
|
blocked_services:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
upstreams:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
whois_info:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/WhoisInfo"
|
||||||
|
disallowed:
|
||||||
|
description: >
|
||||||
|
* "": IP is allowed
|
||||||
|
* not "", e.g. "127.0.0.0/24" - IP is disallowed by "disallowed IP list", and the string contains the matched rule (IP or CIDR)
|
||||||
|
* "not-in-allowed-list" - IP is disallowed by "allowed IP list"
|
||||||
|
type: string
|
||||||
|
|
||||||
|
WhoisInfo:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
key:
|
||||||
|
type: string
|
||||||
|
|
||||||
Clients:
|
Clients:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
|
Loading…
Reference in New Issue