diff --git a/client/babel.config.js b/client/babel.config.js
index 55609d5e..c6fdd790 100644
--- a/client/babel.config.js
+++ b/client/babel.config.js
@@ -9,6 +9,8 @@ module.exports = (api) => {
             '@babel/plugin-proposal-class-properties',
             '@babel/plugin-transform-runtime',
             '@babel/plugin-proposal-object-rest-spread',
+            '@babel/plugin-proposal-nullish-coalescing-operator',
+            '@babel/plugin-proposal-optional-chaining',
         ],
     };
 };
diff --git a/client/package-lock.json b/client/package-lock.json
index 91b1f414..faaa5598 100644
--- a/client/package-lock.json
+++ b/client/package-lock.json
@@ -472,13 +472,21 @@
       }
     },
     "@babel/plugin-proposal-nullish-coalescing-operator": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz",
-      "integrity": "sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw==",
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz",
+      "integrity": "sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.8.3",
+        "@babel/helper-plugin-utils": "^7.10.4",
         "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0"
+      },
+      "dependencies": {
+        "@babel/helper-plugin-utils": {
+          "version": "7.10.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+          "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+          "dev": true
+        }
       }
     },
     "@babel/plugin-proposal-numeric-separator": {
@@ -513,13 +521,21 @@
       }
     },
     "@babel/plugin-proposal-optional-chaining": {
-      "version": "7.9.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz",
-      "integrity": "sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w==",
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.10.4.tgz",
+      "integrity": "sha512-ZIhQIEeavTgouyMSdZRap4VPPHqJJ3NEs2cuHs5p0erH+iz6khB0qfgU8g7UuJkG88+fBMy23ZiU+nuHvekJeQ==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.8.3",
+        "@babel/helper-plugin-utils": "^7.10.4",
         "@babel/plugin-syntax-optional-chaining": "^7.8.0"
+      },
+      "dependencies": {
+        "@babel/helper-plugin-utils": {
+          "version": "7.10.4",
+          "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+          "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+          "dev": true
+        }
       }
     },
     "@babel/plugin-proposal-unicode-property-regex": {
diff --git a/client/package.json b/client/package.json
index 7f154d4d..edf5e424 100644
--- a/client/package.json
+++ b/client/package.json
@@ -44,7 +44,9 @@
     "devDependencies": {
         "@babel/core": "^7.9.6",
         "@babel/plugin-proposal-class-properties": "^7.8.3",
+        "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4",
         "@babel/plugin-proposal-object-rest-spread": "^7.9.6",
+        "@babel/plugin-proposal-optional-chaining": "^7.10.4",
         "@babel/plugin-transform-runtime": "^7.9.6",
         "@babel/preset-env": "^7.9.6",
         "@babel/preset-react": "^7.9.4",
diff --git a/client/src/actions/index.js b/client/src/actions/index.js
index 478a3021..2cef57e6 100644
--- a/client/src/actions/index.js
+++ b/client/src/actions/index.js
@@ -149,7 +149,7 @@ const checkStatus = async (handleRequestSuccess, handleRequestError, attempts =
     try {
         const response = await axios.get('control/status');
         rmTimeout(timeout);
-        if (response && response.status === 200) {
+        if (response?.status === 200) {
             handleRequestSuccess(response);
             if (response.data.running === false) {
                 timeout = setTimeout(
@@ -183,7 +183,7 @@ export const getUpdate = () => async (dispatch, getState) => {
     };
 
     const handleRequestSuccess = (response) => {
-        const responseVersion = response.data && response.data.version;
+        const responseVersion = response.data?.version;
 
         if (dnsVersion !== responseVersion) {
             dispatch(getUpdateSuccess());
diff --git a/client/src/components/Filters/Services/index.js b/client/src/components/Filters/Services/index.js
index 1830be38..e1c9d840 100644
--- a/client/src/components/Filters/Services/index.js
+++ b/client/src/components/Filters/Services/index.js
@@ -17,7 +17,7 @@ const getInitialDataForServices = (initial) => (initial ? initial.reduce(
 const Services = () => {
     const [t] = useTranslation();
     const dispatch = useDispatch();
-    const services = useSelector((store) => store && store.services);
+    const services = useSelector((store) => store?.services);
 
     useEffect(() => {
         dispatch(getBlockedServices());
diff --git a/client/src/components/Logs/Cells/getClientCell.js b/client/src/components/Logs/Cells/getClientCell.js
index b842e0e6..147dd3af 100644
--- a/client/src/components/Logs/Cells/getClientCell.js
+++ b/client/src/components/Logs/Cells/getClientCell.js
@@ -11,23 +11,20 @@ const getClientCell = ({
     row, t, isDetailed, toggleBlocking, autoClients, processingRules,
 }) => {
     const {
-        reason, client, domain, info: { name },
+        reason, client, domain, info: { name, whois_info },
     } = row.original;
 
     const autoClient = autoClients.find((autoClient) => autoClient.name === client);
-    const country = autoClient && autoClient.whois_info && autoClient.whois_info.country;
-    const city = autoClient && autoClient.whois_info && autoClient.whois_info.city;
-    const network = autoClient && autoClient.whois_info && autoClient.whois_info.orgname;
-    const source = autoClient && autoClient.source;
+    const source = autoClient?.source;
 
     const id = nanoid();
 
     const data = {
         address: client,
         name,
-        country,
-        city,
-        network,
+        country: whois_info?.country,
+        city: whois_info?.city,
+        network: whois_info?.orgname,
         source_label: source,
     };
 
diff --git a/client/src/components/Logs/Cells/getDomainCell.js b/client/src/components/Logs/Cells/getDomainCell.js
index 0d460190..bff36c37 100644
--- a/client/src/components/Logs/Cells/getDomainCell.js
+++ b/client/src/components/Logs/Cells/getDomainCell.js
@@ -57,8 +57,8 @@ const getDomainCell = (props) => {
     const sourceData = getSourceData(tracker);
 
     const knownTrackerDataObj = {
-        name_table_header: tracker && tracker.name,
-        category_label: tracker && captitalizeWords(tracker.category),
+        name_table_header: tracker?.name,
+        category_label: hasTracker && captitalizeWords(tracker.category),
         source_label: sourceData
             && <a href={sourceData.url} target="_blank" rel="noopener noreferrer"
                   className="link--green">{sourceData.name}</a>,
diff --git a/client/src/components/Logs/Cells/getResponseCell.js b/client/src/components/Logs/Cells/getResponseCell.js
index f0b390c3..73cd1d2b 100644
--- a/client/src/components/Logs/Cells/getResponseCell.js
+++ b/client/src/components/Logs/Cells/getResponseCell.js
@@ -36,8 +36,7 @@ const getResponseCell = (row, filtering, t, isDetailed) => {
     const { filters, whitelistFilters } = filtering;
     const formattedElapsedMs = formatElapsedMs(elapsedMs, t);
 
-    const statusLabel = t((FILTERED_STATUS_TO_META_MAP[reason]
-        && FILTERED_STATUS_TO_META_MAP[reason].label) || reason);
+    const statusLabel = t(FILTERED_STATUS_TO_META_MAP[reason]?.label || reason);
     const boldStatusLabel = <span className="font-weight-bold">{statusLabel}</span>;
     const filter = getFilterName(filters, whitelistFilters, filterId, t);
 
diff --git a/client/src/components/Logs/Filters/Form.js b/client/src/components/Logs/Filters/Form.js
index df0bc483..21e64322 100644
--- a/client/src/components/Logs/Filters/Form.js
+++ b/client/src/components/Logs/Filters/Form.js
@@ -1,10 +1,18 @@
-import React from 'react';
+import React, { useEffect } from 'react';
 import PropTypes from 'prop-types';
 import { Field, reduxForm } from 'redux-form';
 import { useTranslation } from 'react-i18next';
 import debounce from 'lodash/debounce';
-import { DEBOUNCE_FILTER_TIMEOUT, FORM_NAME, RESPONSE_FILTER } from '../../../helpers/constants';
+import { useDispatch } from 'react-redux';
+import classNames from 'classnames';
+import {
+    DEBOUNCE_FILTER_TIMEOUT,
+    DEFAULT_LOGS_FILTER,
+    FORM_NAME,
+    RESPONSE_FILTER,
+} from '../../../helpers/constants';
 import Tooltip from '../../ui/Tooltip';
+import { setLogsFilter } from '../../../actions/queryLogs';
 
 const renderFilterField = ({
     input,
@@ -16,8 +24,9 @@ const renderFilterField = ({
     autoComplete,
     tooltip,
     meta: { touched, error },
+    onClearInputClick,
 }) => <>
-    <div className="input-group-search">
+    <div className="input-group-search input-group-search__icon--magnifier">
         <svg className="icons icon--small icon--gray">
             <use xlinkHref="#magnifier" />
         </svg>
@@ -31,9 +40,15 @@ const renderFilterField = ({
         disabled={disabled}
         autoComplete={autoComplete}
         aria-label={placeholder} />
-    <span className="logs__notice">
-                <Tooltip text={tooltip} type='tooltip-custom--logs' />
-            </span>
+    <div
+        className={classNames('input-group-search input-group-search__icon--cross', { invisible: input.value.length < 1 })}>
+        <svg className="icons icon--smallest icon--gray" onClick={onClearInputClick}>
+            <use xlinkHref="#cross" />
+        </svg>
+    </div>
+    <span className="input-group-search input-group-search__icon--tooltip">
+        <Tooltip text={tooltip} type='tooltip-custom--logs' />
+    </span>
     {!disabled
     && touched
     && (error && <span className="form__message form__message--error">{error}</span>)}
@@ -42,6 +57,7 @@ const renderFilterField = ({
 renderFilterField.propTypes = {
     input: PropTypes.object.isRequired,
     id: PropTypes.string.isRequired,
+    onClearInputClick: PropTypes.func.isRequired,
     className: PropTypes.string,
     placeholder: PropTypes.string,
     type: PropTypes.string,
@@ -59,13 +75,29 @@ const Form = (props) => {
         className = '',
         responseStatusClass,
         submit,
+        reset,
+        setIsLoading,
     } = props;
 
-    const [t] = useTranslation();
+    const { t } = useTranslation();
+    const dispatch = useDispatch();
 
     const debouncedSubmit = debounce(submit, DEBOUNCE_FILTER_TIMEOUT);
     const zeroDelaySubmit = () => setTimeout(submit, 0);
 
+    const clearInput = async () => {
+        await dispatch(setLogsFilter(DEFAULT_LOGS_FILTER));
+        await reset();
+    };
+
+    const onInputClear = async () => {
+        setIsLoading(true);
+        await clearInput();
+        setIsLoading(false);
+    };
+
+    useEffect(() => clearInput, []);
+
     return (
         <form className="d-flex flex-wrap form-control--container"
               onSubmit={(e) => {
@@ -79,16 +111,17 @@ const Form = (props) => {
                 name="search"
                 component={renderFilterField}
                 type="text"
-                className={`form-control--search form-control--transparent ${className}`}
+                className={classNames('form-control--search form-control--transparent', className)}
                 placeholder={t('domain_or_client')}
                 tooltip={t('query_log_strict_search')}
                 onChange={debouncedSubmit}
+                onClearInputClick={onInputClear}
             />
             <div className="field__select">
                 <Field
                     name="response_status"
                     component="select"
-                    className={`form-control custom-select custom-select--logs custom-select__arrow--left ml-small form-control--transparent ${responseStatusClass}`}
+                    className={classNames('form-control custom-select custom-select--logs custom-select__arrow--left ml-small form-control--transparent', responseStatusClass)}
                     onChange={zeroDelaySubmit}
                 >
                     {Object.values(RESPONSE_FILTER)
@@ -107,6 +140,8 @@ Form.propTypes = {
     className: PropTypes.string,
     responseStatusClass: PropTypes.string,
     submit: PropTypes.func.isRequired,
+    reset: PropTypes.func.isRequired,
+    setIsLoading: PropTypes.func.isRequired,
 };
 
 export default reduxForm({
diff --git a/client/src/components/Logs/Filters/index.js b/client/src/components/Logs/Filters/index.js
index 49744af3..8bb2165c 100644
--- a/client/src/components/Logs/Filters/index.js
+++ b/client/src/components/Logs/Filters/index.js
@@ -33,7 +33,8 @@ const Filters = ({ filter, refreshLogs, setIsLoading }) => {
                 responseStatusClass="d-sm-block"
                 initialValues={filter}
                 onSubmit={onSubmit}
-            />
+                setIsLoading={setIsLoading}
+        />
         </div>
     );
 };
diff --git a/client/src/components/Logs/Logs.css b/client/src/components/Logs/Logs.css
index 0a5939c1..2f12c08d 100644
--- a/client/src/components/Logs/Logs.css
+++ b/client/src/components/Logs/Logs.css
@@ -199,17 +199,6 @@
     position: relative;
 }
 
-.logs__notice {
-    position: relative;
-    z-index: 1;
-    top: 0.5rem;
-    right: 2rem;
-    margin-top: 0.1875rem;
-    font-size: 0.75rem;
-    text-align: left;
-    color: var(--gray-a5);
-}
-
 .logs__whois {
     display: inline;
     font-size: 12px;
@@ -485,10 +474,22 @@
 .input-group-search {
     background-color: transparent;
     position: relative;
-    left: 2rem;
-    top: 0.4rem;
     width: 1.5rem;
     height: 1.5rem;
+    top: 0.4rem;
+}
+
+.input-group-search__icon--magnifier {
+    left: 2rem;
+}
+
+.input-group-search__icon--cross {
+    left: -4.5rem;
+    cursor: pointer;
+}
+
+.input-group-search__icon--tooltip {
+    left: -4rem;
 }
 
 .form-control--container {
diff --git a/client/src/components/Logs/Table.js b/client/src/components/Logs/Table.js
index ccab98bb..6e0649de 100644
--- a/client/src/components/Logs/Table.js
+++ b/client/src/components/Logs/Table.js
@@ -180,6 +180,7 @@ const Table = (props) => {
             minWidth: 123,
             maxHeight: 60,
             headerClassName: 'logs__text',
+            className: 'pb-0',
         },
     ];
 
@@ -279,20 +280,15 @@ const Table = (props) => {
 
                         const hasTracker = !!tracker;
 
-                        const autoClient = autoClients.find(
-                            (autoClient) => autoClient.name === client,
-                        );
+                        const autoClient = autoClients
+                            .find((autoClient) => autoClient.name === client);
 
-                        const country = autoClient && autoClient.whois_info
-                            && autoClient.whois_info.country;
+                        const { whois_info } = info;
+                        const country = whois_info?.country;
+                        const city = whois_info?.city;
+                        const network = whois_info?.orgname;
 
-                        const network = autoClient && autoClient.whois_info
-                            && autoClient.whois_info.orgname;
-
-                        const city = autoClient && autoClient.whois_info
-                            && autoClient.whois_info.city;
-
-                        const source = autoClient && autoClient.source;
+                        const source = autoClient?.source;
 
                         const formattedElapsedMs = formatElapsedMs(elapsedMs, t);
                         const isFiltered = checkFiltered(reason);
@@ -302,8 +298,7 @@ const Table = (props) => {
                             toggleBlocking(buttonType, domain);
                         };
 
-                        const status = t((FILTERED_STATUS_TO_META_MAP[reason]
-                            && FILTERED_STATUS_TO_META_MAP[reason].label) || reason);
+                        const status = t(FILTERED_STATUS_TO_META_MAP[reason]?.label || reason);
                         const statusBlocked = <div className="bg--danger">{status}</div>;
 
                         const protocol = t(SCHEME_TO_PROTOCOL_MAP[client_proto]) || '';
@@ -318,7 +313,7 @@ const Table = (props) => {
                             type_table_header: type,
                             protocol,
                             known_tracker: hasTracker && 'title',
-                            table_name: hasTracker && tracker.name,
+                            table_name: tracker?.name,
                             category_label: hasTracker && captitalizeWords(tracker.category),
                             tracker_source: hasTracker && sourceData
                                 && <a href={sourceData.url} target="_blank" rel="noopener noreferrer"
@@ -326,17 +321,17 @@ const Table = (props) => {
                             response_details: 'title',
                             install_settings_dns: upstream,
                             elapsed: formattedElapsedMs,
-                            response_table_header: response && response.join('\n'),
+                            response_table_header: response?.join('\n'),
                             client_details: 'title',
                             ip_address: client,
-                            name: info && info.name,
+                            name: info?.name,
                             country,
                             city,
                             network,
                             source_label: source,
                             validated_with_dnssec: dnssec_enabled ? Boolean(answer_dnssec) : false,
                             [buttonType]: <div onClick={onToggleBlock}
-                                               className="title--border bg--danger">{t(buttonType)}</div>,
+                                               className="title--border bg--danger text-center">{t(buttonType)}</div>,
                         };
 
                         const detailedDataBlocked = {
@@ -347,7 +342,7 @@ const Table = (props) => {
                             type_table_header: type,
                             protocol,
                             known_tracker: 'title',
-                            table_name: hasTracker && tracker.name,
+                            table_name: tracker?.name,
                             category_label: hasTracker && captitalizeWords(tracker.category),
                             source_label: hasTracker && sourceData
                                 && <a href={sourceData.url} target="_blank" rel="noopener noreferrer"
@@ -355,9 +350,9 @@ const Table = (props) => {
                             response_details: 'title',
                             install_settings_dns: upstream,
                             elapsed: formattedElapsedMs,
-                            response_table_header: response && response.join('\n'),
+                            response_table_header: response?.join('\n'),
                             [buttonType]: <div onClick={onToggleBlock}
-                                               className="title--border">{t(buttonType)}</div>,
+                                               className="title--border text-center">{t(buttonType)}</div>,
                         };
 
                         const detailedDataCurrent = isFiltered ? detailedDataBlocked : detailedData;
diff --git a/client/src/components/Logs/index.js b/client/src/components/Logs/index.js
index 3ac21857..6bfdcb86 100644
--- a/client/src/components/Logs/index.js
+++ b/client/src/components/Logs/index.js
@@ -12,12 +12,12 @@ import Loading from '../ui/Loading';
 import Filters from './Filters';
 import Table from './Table';
 import Disabled from './Disabled';
-import './Logs.css';
 import { getFilteringStatus } from '../../actions/filtering';
 import { getClients } from '../../actions';
 import { getDnsConfig } from '../../actions/dnsConfig';
 import { getLogsConfig } from '../../actions/queryLogs';
 import { addSuccessToast } from '../../actions/toasts';
+import './Logs.css';
 
 const INITIAL_REQUEST = true;
 const INITIAL_REQUEST_DATA = ['', TABLE_FIRST_PAGE, INITIAL_REQUEST];
diff --git a/client/src/components/Settings/Dhcp/index.js b/client/src/components/Settings/Dhcp/index.js
index 8943fb6e..b08b1094 100644
--- a/client/src/components/Settings/Dhcp/index.js
+++ b/client/src/components/Settings/Dhcp/index.js
@@ -32,7 +32,7 @@ class Dhcp extends Component {
         const {
             config, check, processingDhcp, processingConfig,
         } = this.props.dhcp;
-        const otherDhcpFound = check && check.otherServer
+        const otherDhcpFound = check?.otherServer
             && check.otherServer.found === DHCP_STATUS_RESPONSE.YES;
         const filledConfig = Object.keys(config).every((key) => {
             if (key === 'enabled' || key === 'icmp_timeout_msec') {
diff --git a/client/src/components/Settings/Dns/Config/Form.js b/client/src/components/Settings/Dns/Config/Form.js
index 67ee14dc..08514bc8 100644
--- a/client/src/components/Settings/Dns/Config/Form.js
+++ b/client/src/components/Settings/Dns/Config/Form.js
@@ -4,7 +4,6 @@ import { connect } from 'react-redux';
 import { Field, reduxForm, formValueSelector } from 'redux-form';
 import { Trans, withTranslation } from 'react-i18next';
 import flow from 'lodash/flow';
-
 import {
     renderInputField,
     renderRadioField,
@@ -12,7 +11,10 @@ import {
     toNumber,
 } from '../../../../helpers/form';
 import {
-    validateBiggerOrEqualZeroValue, validateIpv4, validateIpv6, validateRequiredValue,
+    validateBiggerOrEqualZeroValue,
+    validateIpv4,
+    validateIpv6,
+    validateRequiredValue,
 } from '../../../../helpers/validators';
 import { BLOCKING_MODES, FORM_NAME } from '../../../../helpers/constants';
 
diff --git a/client/src/components/Toasts/index.js b/client/src/components/Toasts/index.js
index a0278751..d765b097 100644
--- a/client/src/components/Toasts/index.js
+++ b/client/src/components/Toasts/index.js
@@ -9,7 +9,7 @@ import './Toast.css';
 
 const Toasts = (props) => (
         <TransitionGroup className="toasts">
-            {props.toasts.notices && props.toasts.notices.map((toast) => {
+            {props.toasts.notices?.map((toast) => {
                 const { id } = toast;
                 return (
                     <CSSTransition
diff --git a/client/src/components/ui/Guide.js b/client/src/components/ui/Guide.js
index 4d0a48f3..0cb738d8 100644
--- a/client/src/components/ui/Guide.js
+++ b/client/src/components/ui/Guide.js
@@ -120,7 +120,7 @@ const renderDnsPrivacyList = ({ title, list }) => <div className="tab__paragraph
     <strong><Trans>{title}</Trans></strong>
     <ul>{list.map(({ label, components }) => <li key={label}>
         <Trans
-            components={components && components.map((props) => {
+            components={components?.map((props) => {
                 if (React.isValidElement(props)) {
                     return props;
                 }
@@ -198,7 +198,7 @@ const getTabs = ({
         // eslint-disable-next-line react/display-name
         getTitle: () => <div label="dns_privacy" title={t('dns_privacy')}>
             <div className="tab__text">
-                {tlsAddress && tlsAddress.length > 0 && (
+                {tlsAddress?.length > 0 && (
                     <div className="tab__paragraph">
                         <Trans
                             values={{ address: tlsAddress[0] }}
@@ -211,7 +211,7 @@ const getTabs = ({
                         </Trans>
                     </div>
                 )}
-                {httpsAddress && httpsAddress.length > 0 && (
+                {httpsAddress?.length > 0 && (
                     <div className="tab__paragraph">
                         <Trans
                             values={{ address: httpsAddress[0] }}
diff --git a/client/src/components/ui/Icons.css b/client/src/components/ui/Icons.css
index c534d5a4..f5387c68 100644
--- a/client/src/components/ui/Icons.css
+++ b/client/src/components/ui/Icons.css
@@ -9,6 +9,11 @@
     height: 1.5rem;
 }
 
+.icon--smallest {
+    width: 1.2rem;
+    height: 1.2rem;
+}
+
 .icon--gray {
     color: var(--gray-a5);
 }
diff --git a/client/src/helpers/form.js b/client/src/helpers/form.js
index 1b969c54..51cd4c1b 100644
--- a/client/src/helpers/form.js
+++ b/client/src/helpers/form.js
@@ -175,7 +175,7 @@ export const renderSelectField = ({
     </label>
     {!disabled
     && touched
-    && (error && <span className="form__message form__message--error">{error}</span>)}
+    && error && <span className="form__message form__message--error">{error}</span>}
 </Fragment>;
 
 renderSelectField.propTypes = {
diff --git a/client/src/helpers/formatClientCell.js b/client/src/helpers/formatClientCell.js
index 37776af1..9e125588 100644
--- a/client/src/helpers/formatClientCell.js
+++ b/client/src/helpers/formatClientCell.js
@@ -1,4 +1,4 @@
-import React, { Fragment } from 'react';
+import React from 'react';
 import { normalizeWhois } from './helpers';
 import { WHOIS_ICONS } from './constants';
 
@@ -11,12 +11,12 @@ const getFormattedWhois = (whois, t) => {
                 return (
                     <span className="logs__whois text-muted" key={key} title={t(key)}>
                     {icon && (
-                        <Fragment>
+                        <>
                             <svg className="logs__whois-icon icons">
                                 <use xlinkHref={`#${icon}`} />
                             </svg>
                             &nbsp;
-                        </Fragment>
+                        </>
                     )}{whoisInfo[key]}
                 </span>
                 );
diff --git a/client/src/helpers/helpers.js b/client/src/helpers/helpers.js
index 0260248c..cc4d7219 100644
--- a/client/src/helpers/helpers.js
+++ b/client/src/helpers/helpers.js
@@ -142,7 +142,7 @@ export const addClientInfo = (data, clients, param) => (
         const info = clients.find((item) => item[clientIp]) || '';
         return {
             ...row,
-            info: (info && info[clientIp]) || '',
+            info: info?.[clientIp] ?? '',
         };
     })
 );
@@ -342,7 +342,7 @@ export const normalizeTopClients = (topClients) => topClients.reduce(
 
 export const getClientInfo = (clients, ip) => {
     const client = clients
-        .find((item) => item.ip_addrs && item.ip_addrs.find((clientIp) => clientIp === ip));
+        .find((item) => item.ip_addrs?.find((clientIp) => clientIp === ip));
 
     if (!client) {
         return '';
@@ -403,7 +403,7 @@ export const secondsToMilliseconds = (seconds) => {
     return seconds;
 };
 
-export const normalizeRulesTextarea = (text) => text && text.replace(/^\n/g, '')
+export const normalizeRulesTextarea = (text) => text?.replace(/^\n/g, '')
     .replace(/\n\s*\n/g, '\n');
 
 export const isVersionGreater = (currentVersion, previousVersion) => (
@@ -415,7 +415,7 @@ export const normalizeWhois = (whois) => {
         const {
             city, country, ...values
         } = whois;
-        let location = (country && country) || '';
+        let location = country || '';
 
         if (city && location) {
             location = `${location}, ${city}`;
@@ -483,7 +483,7 @@ export const checkParental = (reason) => reason === FILTERED_STATUS.FILTERED_PAR
 export const checkBlockedService = (reason) => reason === FILTERED_STATUS.FILTERED_BLOCKED_SERVICE;
 
 export const getCurrentFilter = (url, filters) => {
-    const filter = filters && filters.find((item) => url === item.url);
+    const filter = filters?.find((item) => url === item.url);
 
     if (filter) {
         const { enabled, name, url } = filter;
diff --git a/client/src/install/Setup/Settings.js b/client/src/install/Setup/Settings.js
index 37a84acc..a939af41 100644
--- a/client/src/install/Setup/Settings.js
+++ b/client/src/install/Setup/Settings.js
@@ -28,9 +28,9 @@ const renderInterfaces = ((interfaces) => (
             flags,
         } = option;
 
-        if (option && ip_addresses && ip_addresses.length > 0) {
+        if (option && ip_addresses?.length > 0) {
             const ip = getInterfaceIp(option);
-            const isDown = flags && flags.includes('down');
+            const isDown = flags?.includes('down');
 
             if (isDown) {
                 return (
diff --git a/client/src/reducers/access.js b/client/src/reducers/access.js
index cf1ad958..e90bb314 100644
--- a/client/src/reducers/access.js
+++ b/client/src/reducers/access.js
@@ -14,9 +14,9 @@ const access = handleActions(
             } = payload;
             const newState = {
                 ...state,
-                allowed_clients: (allowed_clients && allowed_clients.join('\n')) || '',
-                disallowed_clients: (disallowed_clients && disallowed_clients.join('\n')) || '',
-                blocked_hosts: (blocked_hosts && blocked_hosts.join('\n')) || '',
+                allowed_clients: allowed_clients?.join('\n') || '',
+                disallowed_clients: disallowed_clients?.join('\n') || '',
+                blocked_hosts: blocked_hosts?.join('\n') || '',
                 processing: false,
             };
             return newState;
@@ -42,9 +42,9 @@ const access = handleActions(
             } = payload;
             const newState = {
                 ...state,
-                allowed_clients: (allowed_clients && allowed_clients.join('\n')) || '',
-                disallowed_clients: (disallowed_clients && disallowed_clients.join('\n')) || '',
-                blocked_hosts: (blocked_hosts && blocked_hosts.join('\n')) || '',
+                allowed_clients: allowed_clients?.join('\n') || '',
+                disallowed_clients: disallowed_clients?.join('\n') || '',
+                blocked_hosts: blocked_hosts?.join('\n') || '',
                 processingSet: false,
             };
             return newState;
diff --git a/home/auth.go b/home/auth.go
index 3b524d29..3166052b 100644
--- a/home/auth.go
+++ b/home/auth.go
@@ -365,6 +365,7 @@ func parseCookie(cookie string) string {
 	return ""
 }
 
+// nolint(gocyclo)
 func optionalAuth(handler func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
 	return func(w http.ResponseWriter, r *http.Request) {
 
@@ -391,7 +392,11 @@ func optionalAuth(handler func(http.ResponseWriter, *http.Request)) func(http.Re
 			// redirect to login page if not authenticated
 			ok := false
 			cookie, err := r.Cookie(sessionCookieName)
-			if err == nil {
+
+			if glProcessCookie(r) {
+				log.Debug("Auth: authentification was handled by GL-Inet submodule")
+
+			} else if err == nil {
 				r := Context.auth.CheckSession(cookie.Value)
 				if r == 0 {
 					ok = true
@@ -412,8 +417,13 @@ func optionalAuth(handler func(http.ResponseWriter, *http.Request)) func(http.Re
 			}
 			if !ok {
 				if r.URL.Path == "/" || r.URL.Path == "/index.html" {
-					w.Header().Set("Location", "/login.html")
-					w.WriteHeader(http.StatusFound)
+					if glProcessRedirect(w, r) {
+						log.Debug("Auth: redirected to login page by GL-Inet submodule")
+
+					} else {
+						w.Header().Set("Location", "/login.html")
+						w.WriteHeader(http.StatusFound)
+					}
 				} else {
 					w.WriteHeader(http.StatusForbidden)
 					_, _ = w.Write([]byte("Forbidden"))
@@ -510,6 +520,10 @@ func (a *Auth) GetUsers() []User {
 
 // AuthRequired - if authentication is required
 func (a *Auth) AuthRequired() bool {
+	if GLMode {
+		return true
+	}
+
 	a.lock.Lock()
 	r := (len(a.users) != 0)
 	a.lock.Unlock()
diff --git a/home/auth_glinet.go b/home/auth_glinet.go
new file mode 100644
index 00000000..7dd2790d
--- /dev/null
+++ b/home/auth_glinet.go
@@ -0,0 +1,102 @@
+package home
+
+import (
+	"bytes"
+	"encoding/binary"
+	"io/ioutil"
+	"net"
+	"net/http"
+	"os"
+	"time"
+	"unsafe"
+
+	"github.com/AdguardTeam/golibs/log"
+)
+
+// GLMode - enable GL-Inet compatibility mode
+var GLMode bool
+
+var glFilePrefix = "/tmp/gl_token_"
+
+const glTokenTimeoutSeconds = 3600
+const glCookieName = "Admin-Token"
+
+func glProcessRedirect(w http.ResponseWriter, r *http.Request) bool {
+	if !GLMode {
+		return false
+	}
+	// redirect to gl-inet login
+	host, _, _ := net.SplitHostPort(r.Host)
+	url := "http://" + host
+	log.Debug("Auth: redirecting to %s", url)
+	http.Redirect(w, r, url, http.StatusFound)
+	return true
+}
+
+func glProcessCookie(r *http.Request) bool {
+	if !GLMode {
+		return false
+	}
+
+	glCookie, glerr := r.Cookie(glCookieName)
+	if glerr != nil {
+		return false
+	}
+
+	log.Debug("Auth: GL cookie value: %s", glCookie.Value)
+	if glCheckToken(glCookie.Value) {
+		return true
+	}
+	log.Info("Auth: invalid GL cookie value: %s", glCookie)
+	return false
+}
+
+func glCheckToken(sess string) bool {
+	tokenName := glFilePrefix + sess
+	_, err := os.Stat(tokenName)
+	if err != nil {
+		log.Error("os.Stat: %s", err)
+		return false
+	}
+	tokenDate := glGetTokenDate(tokenName)
+	now := uint32(time.Now().UTC().Unix())
+	return now <= (tokenDate + glTokenTimeoutSeconds)
+}
+
+func archIsLittleEndian() bool {
+	var i int32 = 0x01020304
+	u := unsafe.Pointer(&i)
+	pb := (*byte)(u)
+	b := *pb
+	return (b == 0x04)
+}
+
+func glGetTokenDate(file string) uint32 {
+	f, err := os.Open(file)
+	if err != nil {
+		log.Error("os.Open: %s", err)
+		return 0
+	}
+	var dateToken uint32
+	bs, err := ioutil.ReadAll(f)
+	if err != nil {
+		log.Error("ioutil.ReadAll: %s", err)
+		return 0
+	}
+	buf := bytes.NewBuffer(bs)
+
+	if archIsLittleEndian() {
+		err := binary.Read(buf, binary.LittleEndian, &dateToken)
+		if err != nil {
+			log.Error("binary.Read: %s", err)
+			return 0
+		}
+	} else {
+		err := binary.Read(buf, binary.BigEndian, &dateToken)
+		if err != nil {
+			log.Error("binary.Read: %s", err)
+			return 0
+		}
+	}
+	return dateToken
+}
diff --git a/home/auth_glinet_test.go b/home/auth_glinet_test.go
new file mode 100644
index 00000000..171bb84e
--- /dev/null
+++ b/home/auth_glinet_test.go
@@ -0,0 +1,43 @@
+package home
+
+import (
+	"encoding/binary"
+	"io/ioutil"
+	"net/http"
+	"os"
+	"testing"
+	"time"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestAuthGL(t *testing.T) {
+	dir := prepareTestDir()
+	defer func() { _ = os.RemoveAll(dir) }()
+
+	GLMode = true
+	glFilePrefix = dir + "/gl_token_"
+
+	tval := uint32(1)
+	data := make([]byte, 4)
+	if archIsLittleEndian() {
+		binary.LittleEndian.PutUint32(data, tval)
+	} else {
+		binary.BigEndian.PutUint32(data, tval)
+	}
+	assert.Nil(t, ioutil.WriteFile(glFilePrefix+"test", data, 0644))
+	assert.False(t, glCheckToken("test"))
+
+	tval = uint32(time.Now().UTC().Unix() + 60)
+	data = make([]byte, 4)
+	if archIsLittleEndian() {
+		binary.LittleEndian.PutUint32(data, tval)
+	} else {
+		binary.BigEndian.PutUint32(data, tval)
+	}
+	assert.Nil(t, ioutil.WriteFile(glFilePrefix+"test", data, 0644))
+	r, _ := http.NewRequest("GET", "http://localhost/", nil)
+	r.AddCookie(&http.Cookie{Name: glCookieName, Value: "test"})
+	assert.True(t, glProcessCookie(r))
+	GLMode = false
+}
diff --git a/home/home.go b/home/home.go
index e1338038..077455e8 100644
--- a/home/home.go
+++ b/home/home.go
@@ -263,6 +263,7 @@ func run(args options) {
 	}
 
 	sessFilename := filepath.Join(Context.getDataDir(), "sessions.db")
+	GLMode = args.glinetMode
 	Context.auth = InitAuth(sessFilename, config.Users, config.WebSessionTTLHours*60*60)
 	if Context.auth == nil {
 		log.Fatalf("Couldn't initialize Auth module")
@@ -525,6 +526,8 @@ type options struct {
 
 	// runningAsService flag is set to true when options are passed from the service runner
 	runningAsService bool
+
+	glinetMode bool // Activate GL-Inet mode
 }
 
 // loadOptions reads command line arguments and initializes configuration
@@ -559,6 +562,7 @@ func loadOptions() options {
 		{"check-config", "", "Check configuration and exit", nil, func() { o.checkConfig = true }},
 		{"no-check-update", "", "Don't check for updates", nil, func() { o.disableUpdate = true }},
 		{"verbose", "v", "Enable verbose output", nil, func() { o.verbose = true }},
+		{"glinet", "", "Run in GL-Inet compatibility mode", nil, func() { o.glinetMode = true }},
 		{"version", "", "Show the version and exit", nil, func() {
 			fmt.Printf("AdGuardHome %s\n", versionString)
 			os.Exit(0)