diff --git a/src/net.h b/src/net.h
--- a/src/net.h
+++ b/src/net.h
@@ -286,6 +286,7 @@
             LOCK(cs_vAddedNodes);
             vAddedNodes = connOptions.m_added_nodes;
         }
+        m_onion_binds = connOptions.onion_binds;
     }
 
     CConnman(const Config &configIn, uint64_t seed0, uint64_t seed1,
@@ -643,6 +644,12 @@
 
     std::atomic<int64_t> m_next_send_inv_to_incoming{0};
 
+    /**
+     * A vector of -bind=<address>:<port>=onion arguments each of which is
+     * an address and port that are designated for incoming Tor connections.
+     */
+    std::vector<CService> m_onion_binds;
+
     friend struct ::CConnmanTest;
     friend struct ConnmanTestMsg;
 };
@@ -1203,7 +1210,7 @@
           SOCKET hSocketIn, const CAddress &addrIn, uint64_t nKeyedNetGroupIn,
           uint64_t nLocalHostNonceIn, uint64_t nLocalExtraEntropyIn,
           const CAddress &addrBindIn, const std::string &addrNameIn,
-          ConnectionType conn_type_in);
+          ConnectionType conn_type_in, bool inbound_onion = false);
     ~CNode();
     CNode(const CNode &) = delete;
     CNode &operator=(const CNode &) = delete;
@@ -1244,6 +1251,9 @@
     CService addrLocal GUARDED_BY(cs_addrLocal);
     mutable RecursiveMutex cs_addrLocal;
 
+    //! Whether this peer connected via our Tor onion service.
+    const bool m_inbound_onion{false};
+
 public:
     NodeId GetId() const { return id; }
 
diff --git a/src/net.cpp b/src/net.cpp
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -1275,9 +1275,14 @@
     if (NetPermissions::HasFlag(permissionFlags, PF_BLOOMFILTER)) {
         nodeServices = static_cast<ServiceFlags>(nodeServices | NODE_BLOOM);
     }
-    CNode *pnode = new CNode(id, nodeServices, GetBestHeight(), hSocket, addr,
-                             CalculateKeyedNetGroup(addr), nonce, extra_entropy,
-                             addr_bind, "", ConnectionType::INBOUND);
+
+    const bool inbound_onion =
+        std::find(m_onion_binds.begin(), m_onion_binds.end(), addr_bind) !=
+        m_onion_binds.end();
+    CNode *pnode =
+        new CNode(id, nodeServices, GetBestHeight(), hSocket, addr,
+                  CalculateKeyedNetGroup(addr), nonce, extra_entropy, addr_bind,
+                  "", ConnectionType::INBOUND, inbound_onion);
     pnode->AddRef();
     pnode->m_permissionFlags = permissionFlags;
     // If this flag is present, the user probably expect that RPC and QT report
@@ -3204,7 +3209,8 @@
              int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress &addrIn,
              uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn,
              uint64_t nLocalExtraEntropyIn, const CAddress &addrBindIn,
-             const std::string &addrNameIn, ConnectionType conn_type_in)
+             const std::string &addrNameIn, ConnectionType conn_type_in,
+             bool inbound_onion)
     : nTimeConnected(GetSystemTimeInSeconds()), addr(addrIn),
       addrBind(addrBindIn), nKeyedNetGroup(nKeyedNetGroupIn),
       // Don't relay addr messages to peers that we connect to as
@@ -3212,7 +3218,8 @@
       // links from addr traffic).
       id(idIn), nLocalHostNonce(nLocalHostNonceIn),
       nLocalExtraEntropy(nLocalExtraEntropyIn), m_conn_type(conn_type_in),
-      nLocalServices(nLocalServicesIn), nMyStartingHeight(nMyStartingHeightIn) {
+      nLocalServices(nLocalServicesIn), nMyStartingHeight(nMyStartingHeightIn),
+      m_inbound_onion(inbound_onion) {
     hSocket = hSocketIn;
     addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
     hashContinue = BlockHash();