diff --git a/home/clients.go b/home/clients.go
index 759027d8..4ae478be 100644
--- a/home/clients.go
+++ b/home/clients.go
@@ -7,11 +7,18 @@ import (
 	"net"
 	"net/http"
 	"os"
+	"os/exec"
 	"runtime"
 	"strings"
 	"sync"
+	"time"
 
 	"github.com/AdguardTeam/golibs/log"
+	"github.com/AdguardTeam/golibs/utils"
+)
+
+const (
+	clientsUpdatePeriod = 1 * time.Hour
 )
 
 // Client information
@@ -40,8 +47,10 @@ type clientJSON struct {
 type clientSource uint
 
 const (
-	ClientSourceHostsFile clientSource = 0 // from /etc/hosts
-	ClientSourceRDNS      clientSource = 1 // from rDNS
+	// Priority: etc/hosts > ARP > rDNS
+	ClientSourceRDNS      clientSource = 0 // from rDNS
+	ClientSourceARP       clientSource = 1 // from 'arp -a'
+	ClientSourceHostsFile clientSource = 2 // from /etc/hosts
 )
 
 // ClientHost information
@@ -68,7 +77,15 @@ func clientsInit() {
 	clients.ipIndex = make(map[string]*Client)
 	clients.ipHost = make(map[string]ClientHost)
 
-	clientsAddFromHostsFile()
+	go periodicClientsUpdate()
+}
+
+func periodicClientsUpdate() {
+	for {
+		clientsAddFromHostsFile()
+		clientsAddFromSystemARP()
+		time.Sleep(clientsUpdatePeriod)
+	}
 }
 
 func clientsGetList() map[string]*Client {
@@ -240,13 +257,16 @@ func clientUpdate(name string, c Client) error {
 	return nil
 }
 
+// Add new IP -> Host pair
+// Use priority of the source (etc/hosts > ARP > rDNS)
+//  so we overwrite existing entries with an equal or higher priority
 func clientAddHost(ip, host string, source clientSource) (bool, error) {
 	clients.lock.Lock()
 	defer clients.lock.Unlock()
 
 	// check index
-	_, ok := clients.ipHost[ip]
-	if ok {
+	c, ok := clients.ipHost[ip]
+	if ok && c.Source > source {
 		return false, nil
 	}
 
@@ -254,7 +274,7 @@ func clientAddHost(ip, host string, source clientSource) (bool, error) {
 		Host:   host,
 		Source: source,
 	}
-	log.Tracef("'%s': '%s' -> [%d]", host, ip, len(clients.ipHost))
+	log.Tracef("'%s' -> '%s' [%d]", ip, host, len(clients.ipHost))
 	return true, nil
 }
 
@@ -296,6 +316,52 @@ func clientsAddFromHostsFile() {
 	log.Info("Added %d client aliases from %s", n, hostsFn)
 }
 
+// Add IP -> Host pairs from the system's `arp -a` command output
+// The command's output is:
+// HOST (IP) at MAC on IFACE
+func clientsAddFromSystemARP() {
+
+	if runtime.GOOS == "windows" {
+		return
+	}
+
+	cmd := exec.Command("arp", "-a")
+	log.Tracef("executing %s %v", cmd.Path, cmd.Args)
+	data, err := cmd.Output()
+	if err != nil || cmd.ProcessState.ExitCode() != 0 {
+		log.Debug("command %s has failed: %v code:%d",
+			cmd.Path, err, cmd.ProcessState.ExitCode())
+		return
+	}
+
+	n := 0
+	lines := strings.Split(string(data), "\n")
+	for _, ln := range lines {
+
+		open := strings.Index(ln, " (")
+		close := strings.Index(ln, ") ")
+		if open == -1 || close == -1 || open >= close {
+			continue
+		}
+
+		host := ln[:open]
+		ip := ln[open+2 : close]
+		if utils.IsValidHostname(host) != nil || net.ParseIP(ip) == nil {
+			continue
+		}
+
+		ok, e := clientAddHost(ip, host, ClientSourceARP)
+		if e != nil {
+			log.Tracef("%s", e)
+		}
+		if ok {
+			n++
+		}
+	}
+
+	log.Info("Added %d client aliases from 'arp -a' command output", n)
+}
+
 type clientHostJSON struct {
 	IP     string `json:"ip"`
 	Name   string `json:"name"`
@@ -342,8 +408,11 @@ func handleGetClients(w http.ResponseWriter, r *http.Request) {
 			Name: ch.Host,
 		}
 		cj.Source = "etc/hosts"
-		if ch.Source == ClientSourceRDNS {
+		switch ch.Source {
+		case ClientSourceRDNS:
 			cj.Source = "rDNS"
+		case ClientSourceARP:
+			cj.Source = "ARP"
 		}
 		data.AutoClients = append(data.AutoClients, cj)
 	}
diff --git a/home/clients_test.go b/home/clients_test.go
index a8cb44c2..020c2874 100644
--- a/home/clients_test.go
+++ b/home/clients_test.go
@@ -104,17 +104,29 @@ func TestClients(t *testing.T) {
 	}
 
 	// add host client
-	b, e = clientAddHost("1.1.1.1", "host", ClientSourceHostsFile)
+	b, e = clientAddHost("1.1.1.1", "host", ClientSourceARP)
 	if !b || e != nil {
 		t.Fatalf("clientAddHost")
 	}
 
 	// failed add - ip exists
-	b, e = clientAddHost("1.1.1.1", "host", ClientSourceHostsFile)
+	b, e = clientAddHost("1.1.1.1", "host1", ClientSourceRDNS)
 	if b || e != nil {
 		t.Fatalf("clientAddHost - ip exists")
 	}
 
+	// overwrite with new data
+	b, e = clientAddHost("1.1.1.1", "host2", ClientSourceARP)
+	if !b || e != nil {
+		t.Fatalf("clientAddHost - overwrite with new data")
+	}
+
+	// overwrite with new data (higher priority)
+	b, e = clientAddHost("1.1.1.1", "host3", ClientSourceHostsFile)
+	if !b || e != nil {
+		t.Fatalf("clientAddHost - overwrite with new data (higher priority)")
+	}
+
 	// get
 	if !clientExists("1.1.1.1") {
 		t.Fatalf("clientAddHost")