diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json
index 14f353aa..44a64bea 100644
--- a/client/src/__locales/en.json
+++ b/client/src/__locales/en.json
@@ -187,6 +187,15 @@
"query_log_disabled": "The query log is disabled and can be configured in the <0>settings0>",
"query_log_strict_search": "Use double quotes for strict search",
"query_log_retention_confirm": "Are you sure you want to change query log retention? If you decrease the interval value, some data will be lost",
+ "dns_config": "DNS configuration",
+ "blocking_mode": "Blocking mode",
+ "nxdomain": "NXDOMAIN",
+ "null_ip": "Null IP",
+ "custom_ip": "Custom IP",
+ "blocking_ipv4": "Blocking IPv4",
+ "blocking_ipv6": "Blocking IPv6",
+ "form_enter_rate_limit": "Enter rate limit",
+ "rate_limit": "Rate limit",
"source_label": "Source",
"found_in_known_domain_db": "Found in the known domains database.",
"category_label": "Category",
diff --git a/client/src/actions/dnsConfig.js b/client/src/actions/dnsConfig.js
new file mode 100644
index 00000000..1976613e
--- /dev/null
+++ b/client/src/actions/dnsConfig.js
@@ -0,0 +1,35 @@
+import { createAction } from 'redux-actions';
+
+import apiClient from '../api/Api';
+import { addErrorToast, addSuccessToast } from './index';
+
+export const getDnsConfigRequest = createAction('GET_DNS_CONFIG_REQUEST');
+export const getDnsConfigFailure = createAction('GET_DNS_CONFIG_FAILURE');
+export const getDnsConfigSuccess = createAction('GET_DNS_CONFIG_SUCCESS');
+
+export const getDnsConfig = () => async (dispatch) => {
+ dispatch(getDnsConfigRequest());
+ try {
+ const data = await apiClient.getDnsConfig();
+ dispatch(getDnsConfigSuccess(data));
+ } catch (error) {
+ dispatch(addErrorToast({ error }));
+ dispatch(getDnsConfigFailure());
+ }
+};
+
+export const setDnsConfigRequest = createAction('SET_DNS_CONFIG_REQUEST');
+export const setDnsConfigFailure = createAction('SET_DNS_CONFIG_FAILURE');
+export const setDnsConfigSuccess = createAction('SET_DNS_CONFIG_SUCCESS');
+
+export const setDnsConfig = config => async (dispatch) => {
+ dispatch(setDnsConfigRequest());
+ try {
+ await apiClient.setDnsConfig(config);
+ dispatch(addSuccessToast('config_successfully_saved'));
+ dispatch(setDnsConfigSuccess(config));
+ } catch (error) {
+ dispatch(addErrorToast({ error }));
+ dispatch(setDnsConfigFailure());
+ }
+};
diff --git a/client/src/actions/index.js b/client/src/actions/index.js
index d01130f6..4583c1ae 100644
--- a/client/src/actions/index.js
+++ b/client/src/actions/index.js
@@ -91,17 +91,9 @@ export const toggleProtectionSuccess = createAction('TOGGLE_PROTECTION_SUCCESS')
export const toggleProtection = status => async (dispatch) => {
dispatch(toggleProtectionRequest());
- let successMessage = '';
-
try {
- if (status) {
- successMessage = 'disabled_protection';
- await apiClient.disableGlobalProtection();
- } else {
- successMessage = 'enabled_protection';
- await apiClient.enableGlobalProtection();
- }
-
+ const successMessage = status ? 'disabled_protection' : 'enabled_protection';
+ await apiClient.setDnsConfig({ protection_enabled: !status });
dispatch(addSuccessToast(successMessage));
dispatch(toggleProtectionSuccess());
} catch (error) {
diff --git a/client/src/api/Api.js b/client/src/api/Api.js
index 2393a89d..77dda64b 100644
--- a/client/src/api/Api.js
+++ b/client/src/api/Api.js
@@ -30,8 +30,6 @@ class Api {
GLOBAL_SET_UPSTREAM_DNS = { path: 'set_upstreams_config', method: 'POST' };
GLOBAL_TEST_UPSTREAM_DNS = { path: 'test_upstream_dns', method: 'POST' };
GLOBAL_VERSION = { path: 'version.json', method: 'POST' };
- GLOBAL_ENABLE_PROTECTION = { path: 'enable_protection', method: 'POST' };
- GLOBAL_DISABLE_PROTECTION = { path: 'disable_protection', method: 'POST' };
GLOBAL_UPDATE = { path: 'update', method: 'POST' };
startGlobalFiltering() {
@@ -76,16 +74,6 @@ class Api {
return this.makeRequest(path, method, config);
}
- enableGlobalProtection() {
- const { path, method } = this.GLOBAL_ENABLE_PROTECTION;
- return this.makeRequest(path, method);
- }
-
- disableGlobalProtection() {
- const { path, method } = this.GLOBAL_DISABLE_PROTECTION;
- return this.makeRequest(path, method);
- }
-
getUpdate() {
const { path, method } = this.GLOBAL_UPDATE;
return this.makeRequest(path, method);
@@ -546,6 +534,24 @@ class Api {
const { path, method } = this.GET_PROFILE;
return this.makeRequest(path, method);
}
+
+ // DNS config
+ GET_DNS_CONFIG = { path: 'dns_info', method: 'GET' };
+ SET_DNS_CONFIG = { path: 'dns_config', method: 'POST' };
+
+ getDnsConfig() {
+ const { path, method } = this.GET_DNS_CONFIG;
+ return this.makeRequest(path, method);
+ }
+
+ setDnsConfig(data) {
+ const { path, method } = this.SET_DNS_CONFIG;
+ const config = {
+ data,
+ headers: { 'Content-Type': 'application/json' },
+ };
+ return this.makeRequest(path, method, config);
+ }
}
const apiClient = new Api();
diff --git a/client/src/components/Settings/DnsConfig/Form.js b/client/src/components/Settings/DnsConfig/Form.js
new file mode 100644
index 00000000..4cfdff35
--- /dev/null
+++ b/client/src/components/Settings/DnsConfig/Form.js
@@ -0,0 +1,120 @@
+import React, { Fragment } from 'react';
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+import { Field, reduxForm, formValueSelector } from 'redux-form';
+import { Trans, withNamespaces } from 'react-i18next';
+import flow from 'lodash/flow';
+
+import { renderField, renderRadioField, required, ipv4, ipv6, isPositive, toNumber } from '../../../helpers/form';
+import { BLOCKING_MODES } from '../../../helpers/constants';
+
+const getFields = (processing, t) => Object.values(BLOCKING_MODES).map(mode => (
+