"ip": "<CurrentdynamicIPaddress>", // set if static=no
}
}
If `other_server.found` is:
*`no`: everything is fine - there is no other DHCP server
*`yes`: we found another DHCP server. UI shows a warning.
*`error`: we failed to determine whether there's another DHCP server. `other_server.error` contains error details. UI shows a warning.
If `static_ip.static` is:
*`yes`: everything is fine - server uses static IP address.
*`no`: `static_ip.ip` contains the current dynamic IP address which we may set as static. In this case UI shows a warning:
Your system uses dynamic IP address configuration for interface <CURRENTINTERFACENAME>. In order to use DHCP server a static IP address must be set. Your current IP address is <static_ip.ip>. We will automatically set this IP address as static if you press Enable DHCP button.
*`error`: this means that the server failed to check for a static IP. In this case UI shows a warning:
In order to use DHCP server a static IP address must be set. We failed to determine if this network interface is configured using static IP address. Please set a static IP address manually.
### "Enable DHCP" command
Request:
POST /control/dhcp/set_config
{
"enabled":true,
"interface_name":"vboxnet0",
"gateway_ip":"192.169.56.1",
"subnet_mask":"255.255.255.0",
"range_start":"192.169.56.3",
"range_end":"192.169.56.3",
"lease_duration":60,
"icmp_timeout_msec":0
}
Response:
200 OK
OK
### Static IP check/set
Before enabling DHCP server we have to make sure the network interface we use has a static IP configured.
#### Phase 1
On Debian systems DHCP is configured by `/etc/dhcpcd.conf`.
To detect if a static IP is used currently we search for line
interface eth0
and then look for line
static ip_address=...
If the interface already has a static IP, everything is set up, we don't have to change anything.
To get the current IP address along with netmask we execute
On Ubuntu DHCP for a network interface can't be disabled via `dhcpcd.conf`. This must be configured in `/etc/netplan/01-netcfg.yaml`.
Fedora doesn't use `dhcpcd.conf` configuration at all.
Step 1.
To set a static IP address we add these lines to `dhcpcd.conf`:
interface eth0
static ip_address=192.168.0.1/24
static routers=192.168.0.1
static domain_name_servers=192.168.0.1
* Don't set 'routers' if we couldn't find gateway IP
* Set 'domain_name_servers' equal to our IP
Step 2.
If we would set a different IP address, we'd need to replace the IP address for the current network configuration. But currently this step isn't necessary.
When a client requests information from DNS server, he's identified by IP address.
Administrator can set a name for a client with a known IP and also override global settings for this client. The name is used to improve readability of DNS logs: client's name is shown in UI next to its IP address. The names are loaded from 3 sources:
* automatically from "/etc/hosts" file. It's a list of `IP<->Name` entries which is loaded once on AGH startup from "/etc/hosts" file.
* automatically using rDNS. It's a list of `IP<->Name` entries which is added in runtime using rDNS mechanism when a client first makes a DNS request.
* manually configured via UI. It's a list of client's names and their settings which is loaded from configuration file and stored on disk.
### Per-client settings
UI provides means to manage the list of known clients (List/Add/Update/Delete) and their settings. These settings are stored in configuration file as an array of objects.
Notes:
*`name`, `ip` and `mac` values are unique.
*`ip`&`mac` values can't be set both at the same time.
* If `mac` is set and DHCP server is enabled, IP is taken from DHCP lease table.
* If `use_global_settings` is true, then DNS responses for this client are processed and filtered using global settings.
* If `use_global_blocked_services` is false, then the client-specific settings are used to override (enable or disable) global Blocked Services settings.
When a new DNS request is received and processed, we store information about this event in "query log". It is a file on disk in JSON format:
{
"Question":"...","
Answer":"...",
"Result":{
"IsFiltered":true,
"Reason":3,
"Rule":"...",
"FilterID":1
},
"Time":"...",
"Elapsed":12345,
"IP":"127.0.0.1"
}
### Adding new data
First, new data is stored in a memory region. When this array is filled to a particular amount of entries (e.g. 5000), we flush this data to a file and clear the array.
### Getting data
When UI asks for data from query log (see "API: Get query log"), server reads the newest entries from memory array and the file. The maximum number of items returned per one request is limited by configuration.
### Removing old data
We store data for a limited amount of time - the log file is automatically rotated.
### API: Get query log
Request:
POST /control/querylog
{
older_than: "2006-01-02T15:04:05.999999999Z07:00" // must be "" for the first request
filter:{
domain: "..."
client: "..."
question_type: "A" | "AAAA"
response_status: "" | "filtered"
}
}
If `older_than` value is set, server returns the next chunk of entries that are older than this time stamp. This setting is used for paging. UI sets this value to `""` on the first request and gets the latest log entries. To get the older entries, UI sets this value to the timestamp of the last (the oldest) entry from the previous response from Server.
If "filter" settings are set, server returns only entries that match the specified request.
For `filter.domain` and `filter.client` the server matches substrings by default: `adguard.com` matches `www.adguard.com`. Strict matching can be enabled by enclosing the value in double quotes: `"adguard.com"` matches `adguard.com` but doesn't match `www.adguard.com`.
Filters can be updated either manually by request from UI or automatically.
Auto-update interval can be configured in UI. If it is 0, auto-update is disabled.
When the last modification date of filter files is older than auto-update interval, auto-update procedure is started.
If an enabled filter file doesn't exist, it's downloaded on application startup. This includes the case when installation wizard is completed and there are no filter files yet.
When auto-update time comes, server starts the update procedure by downloading filter files. After new filter files are in place, it restarts DNS filtering module with new rules.
Only filters that are enabled by configuration can be updated.
As a result of the update procedure, all enabled filter files are written to disk, refreshed (their last modification date is equal to the current time) and loaded.
After user completes the steps of installation wizard, he must log in into dashboard using his name and password. After user successfully logs in, he gets the Cookie which allows the server to authenticate him next time without password. After the Cookie is expired, user needs to perform log-in operation again. All requests without a proper Cookie get redirected to Log-In page with prompt for name and password.
YAML configuration:
users:
- name: "..."
password: "..." // bcrypt hash
...
Session DB file:
session="..." expire=123456
...
Session data is SHA(random()+name+password).
Expiration time is UNIX time when cookie gets expired.
Any request to server must come with Cookie header:
GET /...
Cookie: session=...
If not authenticated, server sends a redirect response:
302 Found
Location: /login.html
### Reset password
There is no mechanism to reset the password. Instead, the administrator must use `htpasswd` utility to generate a new hash:
htpasswd -B -n -b username password
It will print `username:<HASH>` to the terminal. `<HASH>` value may be used in AGH YAML configuration file as a value to `password` setting:
users:
- name: "..."
password: <HASH>
### API: Log in
Perform a log-in operation for administrator. Server generates a session for this name+password pair, stores it in file. UI needs to perform all requests with this value inside Cookie HTTP header.
Request:
POST /control/login
{
name: "..."
password: "..."
}
Response:
200 OK
Set-Cookie: session=...; Expires=Wed, 09 Jun 2021 10:18:14 GMT; Path=/; HttpOnly
### API: Log out
Perform a log-out operation for administrator. Server removes the session from its DB and sets an expired cookie value.
Request:
GET /control/logout
Response:
302 Found
Location: /login.html
Set-Cookie: session=...; Expires=Thu, 01 Jan 1970 00:00:00 GMT