Build OpenSnitch v1.8.0 RPMs for Fedora with Per-VM Identity Patch (Fixing the "Identity Crisis")

Original forum link
https://forum.qubes-os.org/t/40366
Original poster
hUt4Ke107Y7VyK
Editors
hUt4Ke107Y7VyK
Created at
2026-04-03 16:21:35
Last wiki edit
2026-04-03 16:54:42
Revisions
2 revisions
Posts count
10
Likes count
4

Some time ago, I posted a workaround for running OpenSnitch across multiple VMs called Split-OpenSnitch with Per-VM Identity.

There is now a much better way to solve this natively! I have submitted a PR to the upstream OpenSnitch project that solves the node identity problem by using node_id as the canonical remote node identity. The PR is still pending, but I have successfully tested it on a Fedora 43 VM running the UI alongside 4 daemon nodes.

For anyone who wants to test this out on Qubes OS with Fedora templates, here is a complete guide to patching OpenSnitch v1.8.0 and building the RPM packages locally.

1. Install Build Dependencies

First, you need to install the system build tools and libraries:

sudo dnf install -y \
  git rpm-build rpmdevtools \
  golang protobuf-compiler golang-google-protobuf protoc-gen-go-grpc \
  clang llvm make gcc \
  libnetfilter_queue-devel libpcap-devel \
  python3-devel python3-setuptools python3-pip python3-packaging \
  qt5-linguist

For runtime and testing after installation, these packages are also highly recommended:

sudo dnf install -y \
  python3-pyqt6 python3-protobuf python3-grpcio \
  python3-inotify python3-slugify python3-grpcio python3-grpcio-tools

2. Save the #1577 and Fedora Build Fixes Patches

To successfully package v1.8.0 on Fedora, you will need a few minor build tweaks. Expand the section below, copy the patch text, and save it as 0002-v1.8.0-local-fedora-rpm-build-fixes.patch in your working directory.

Fedora Build Fixes Patch (0002-v1.8.0-local-fedora-rpm-build-fixes.patch)
From 6f756561842d4e090e8e9e51d2c6766d95dd904f Mon Sep 17 00:00:00 2001
From: nyymi <a01@truewall.eu>
Date: Fri, 3 Apr 2026 08:12:45 +0300
Subject: [PATCH] build: local Fedora RPM packaging fixes for v1.8.0

---
 ebpf_prog/Makefile                         |  3 ++-
 ui/i18n/generate_i18n.sh                   |  5 ++++-
 utils/packaging/daemon/rpm/opensnitch.spec | 13 ++++++-------
 utils/packaging/ui/rpm/opensnitch-ui.spec  |  8 ++++----
 4 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/ebpf_prog/Makefile b/ebpf_prog/Makefile
index 558508fe..747cc74c 100644
--- a/ebpf_prog/Makefile
+++ b/ebpf_prog/Makefile
@@ -58,13 +58,14 @@ CFLAGS = -I. \
    -Wno-address-of-packed-member \
    -Wno-tautological-compare \
    -Wno-unknown-warning-option  \
+   -fms-extensions \
    -fno-stack-protector \
    -g -O2 -emit-llvm

 all: $(BIN)

 %.bc: %.c
-   $(CC) $(CFLAGS) -c $<
+   $(CC) $(CFLAGS) -c $< -o $@

 %.o: %.bc
    $(LLC) -march=bpf -mcpu=generic -filetype=obj -o $@ $<
diff --git a/ui/i18n/generate_i18n.sh b/ui/i18n/generate_i18n.sh
index 55622ea9..1babffc5 100755
--- a/ui/i18n/generate_i18n.sh
+++ b/ui/i18n/generate_i18n.sh
@@ -3,7 +3,10 @@
 app_name="opensnitch"
 langs_dir="./locales"
 lrelease_bin=""
-for lbin in $LRELEASE lrelease lrelease6 lrelease-qt6
+# On some distros the Qt linguist tools live under qt5/qt6 libexec paths,
+# but are not added to the user PATH.
+PATH=$PATH:/usr/lib/qt6/bin:/usr/lib64/qt6/bin:/usr/lib64/qt5/bin/
+for lbin in $LRELEASE lrelease lrelease6 lrelease-qt6 lrelease-qt5
 do
     lrelease_bin="$(command -v $lbin)"
     if [ -n "$lrelease_bin" ]; then
diff --git a/utils/packaging/daemon/rpm/opensnitch.spec b/utils/packaging/daemon/rpm/opensnitch.spec
index ecccfa51..01af46b0 100644
--- a/utils/packaging/daemon/rpm/opensnitch.spec
+++ b/utils/packaging/daemon/rpm/opensnitch.spec
@@ -1,6 +1,6 @@
 Name:           opensnitch
 Version:        1.8.0
-Release:        1%{?dist}
+Release:        1.qubes1%{?dist}
 Summary:        OpenSnitch is a GNU/Linux interactive application firewall

 License:        GPLv3+
@@ -31,12 +31,11 @@ rm -rf %{buildroot}
 %setup

 %build
-mkdir -p go/src/github.com/evilsocket
-ln -s $(pwd) go/src/github.com/evilsocket/opensnitch
-export GOPATH=$(pwd)/go
-cd go/src/github.com/evilsocket/opensnitch/
-make protocol
-cd go/src/github.com/evilsocket/opensnitch/daemon/
+mkdir -p daemon/ui/protocol
+protoc -Iproto proto/ui.proto --go_out=daemon/ui/protocol --go-grpc_out=daemon/ui/protocol --go_opt=paths=source_relative --go-grpc_opt=paths=source_relative
+perl -0pi -e 's/SupportPackageIsVersion8/SupportPackageIsVersion7/g; s/cOpts := append\(\[\]grpc\.CallOption\{grpc\.StaticMethod\(\)\}, opts\.\.\.\)/cOpts := opts/g' daemon/ui/protocol/ui_grpc.pb.go
+make -C ebpf_prog KERNEL_VER="$(uname -r)"
+cd daemon/
 go mod vendor
 go build -o opensnitchd .

diff --git a/utils/packaging/ui/rpm/opensnitch-ui.spec b/utils/packaging/ui/rpm/opensnitch-ui.spec
index be325807..f73b7a8c 100644
--- a/utils/packaging/ui/rpm/opensnitch-ui.spec
+++ b/utils/packaging/ui/rpm/opensnitch-ui.spec
@@ -1,8 +1,7 @@
 %define name opensnitch-ui
 %define version 1.8.0
 %define unmangled_version 1.8.0
-%define release 1
-%define __python python3
+%define release 1.qubes1
 %define desktop_file opensnitch_ui.desktop

 Summary: Prompt service and UI for the OpenSnitch interactive application firewall.
@@ -75,13 +74,14 @@ fi


 %build
+export PATH=/usr/lib64/qt5/bin:/usr/lib64/qt6/bin:/usr/lib/qt6/bin:$PATH
 cd i18n; make; cd ..
 pyrcc5 -o opensnitch/resources_rc.py opensnitch/res/resources.qrc
 find opensnitch/proto/ -name 'ui_pb2_grpc.py' -exec sed -i 's/^import ui_pb2/from . import ui_pb2/' {} \;
-python3 setup.py build
+/usr/bin/python3 setup.py build

 %install
-python3 setup.py install --install-lib=/usr/lib/python3/dist-packages/ --single-version-externally-managed -O1 --root=$RPM_BUILD_ROOT --prefix=/usr --record=INSTALLED_FILES --install-scripts=/usr/bin
+/usr/bin/python3 setup.py install --install-lib=/usr/lib/python3/dist-packages/ --single-version-externally-managed -O1 --root=$RPM_BUILD_ROOT --prefix=/usr --record=INSTALLED_FILES --install-scripts=/usr/bin

 %clean
 rm -rf $RPM_BUILD_ROOT
-- 
2.53.0

Expand the section below, copy the patch text, and save it as 0001-v1.8.0-ui-use-node_id-as-canonical-remote-node-identity.patch in your working directory.

#1577 Patch (0001-v1.8.0-ui-use-node_id-as-canonical-remote-node-identity.patch)
From 65c270de28f7445ae1e23ea719de1b82a0c77b59 Mon Sep 17 00:00:00 2001
From: nyymi <a01@truewall.eu>
Date: Fri, 3 Apr 2026 08:01:47 +0300
Subject: [PATCH] ui: use node_id as canonical remote node identity

---
 daemon/ui/notifications.go    |   1 +
 proto/ui.proto                |   1 +
 ui/opensnitch/nodes.py        |  63 +++++--
 ui/opensnitch/proto/ui_pb2.py | 316 ++++++++++++++++++++++++++++++++--
 ui/opensnitch/service.py      |   9 +-
 5 files changed, 360 insertions(+), 30 deletions(-)

diff --git a/daemon/ui/notifications.go b/daemon/ui/notifications.go
index 16003bba..a1385d9d 100644
--- a/daemon/ui/notifications.go
+++ b/daemon/ui/notifications.go
@@ -51,6 +51,7 @@ func (c *Client) getClientConfig() *protocol.ClientConfig {
    return &protocol.ClientConfig{
        Id:                uint64(ts.UnixNano()),
        Name:              nodeName,
+       NodeId:            nodeName,
        Version:           nodeVersion,
        IsFirewallRunning: firewall.IsRunning(),
        Config:            strings.Replace(string(raw), "\n", "", -1),
diff --git a/proto/ui.proto b/proto/ui.proto
index f0c9640c..13b88604 100644
--- a/proto/ui.proto
+++ b/proto/ui.proto
@@ -258,6 +258,7 @@ message ClientConfig {
     uint32 logLevel = 6;
     repeated Rule rules = 7;
     SysFirewall systemFirewall = 8;
+    string node_id = 9;
 }

 /* Notification message is sent to the clients (daemons) from the GUI (server)
diff --git a/ui/opensnitch/nodes.py b/ui/opensnitch/nodes.py
index 466b78fe..3582b67b 100644
--- a/ui/opensnitch/nodes.py
+++ b/ui/opensnitch/nodes.py
@@ -32,6 +32,7 @@ class Nodes(QObject):
         self._db = Database.instance()
         self._rules = Rules()
         self._nodes = {}
+        self._peer_map = {}
         self._notifications_sent = {}
         self._interfaces = NetworkInterfaces()

@@ -40,18 +41,28 @@ class Nodes(QObject):

     def add(self, _peer, client_config=None):
         try:
-            proto, addr = self.get_addr(_peer)
-            peer = proto+":"+addr
+            peer = self._get_node_key(_peer, client_config)
+            now = datetime.now()
             if peer not in self._nodes:
                 self._nodes[peer] = {
+                        'session': {
+                            'peer': _peer,
+                            'last_seen': now
+                        },
                         'notifications': Queue(),
                         'online':        True,
-                        'last_seen':     datetime.now()
+                        'last_seen':     now
                         }
             else:
-                self._nodes[peer]['last_seen'] = datetime.now()
+                prev_peer = self._nodes[peer].get('session', {}).get('peer')
+                if prev_peer is not None and prev_peer != _peer:
+                    self._peer_map.pop(prev_peer, None)
+                self._nodes[peer]['last_seen'] = now
+                self._nodes[peer]['session']['peer'] = _peer
+                self._nodes[peer]['session']['last_seen'] = now

             self._nodes[peer]['online'] = True
+            self._peer_map[_peer] = peer
             self.add_data(peer, client_config)
             self.insert(peer)

@@ -143,20 +154,23 @@ class Nodes(QObject):
     def delete_all(self):
         self.send_notifications(None)
         self._nodes = {}
+        self._peer_map = {}
         self.nodesUpdated.emit(self.count())

     def delete(self, peer):
+        addr = self._resolve_node_key(peer)
         try:
-            proto, addr = self.get_addr(peer)
-            addr = "%s:%s" % (proto, addr)
             # Force the node to get one new item from queue,
             # in order to loop and exit.
             self._nodes[addr]['notifications'].put(None)
-        except:
-            addr = peer
+        except Exception:
+            pass

         if addr in self._nodes:
             del self._nodes[addr]
+            for mapped_peer, node_key in list(self._peer_map.items()):
+                if mapped_peer == peer or node_key == addr:
+                    del self._peer_map[mapped_peer]
             self.nodesUpdated.emit(self.count())

     def get(self):
@@ -164,6 +178,7 @@ class Nodes(QObject):

     def get_node(self, addr):
         try:
+            addr = self._resolve_node_key(addr)
             return self._nodes[addr]
         except:
             return None
@@ -173,6 +188,7 @@ class Nodes(QObject):

     def get_node_hostname(self, addr):
         try:
+            addr = self._resolve_node_key(addr)
             if addr not in self._nodes:
                 return ""
             return self._nodes[addr]['data'].name
@@ -182,6 +198,7 @@ class Nodes(QObject):

     def get_node_config(self, addr):
         try:
+            addr = self._resolve_node_key(addr)
             if addr not in self._nodes:
                 return None
             return self._nodes[addr]['data'].config
@@ -202,7 +219,7 @@ class Nodes(QObject):

     def get_addr(self, peer):
         try:
-            peer = peer.split(":")
+            peer = self._split_peer(self._resolve_node_key(peer))
             # WA for backward compatibility
             if peer[0] == "unix" and peer[1] == "":
                 peer[1] = "/local"
@@ -211,6 +228,25 @@ class Nodes(QObject):
             print(self.LOG_TAG, "get_addr() error getting addr:", peer)
             return peer

+    def _split_peer(self, peer):
+        return peer.split(":")
+
+    def _resolve_node_key(self, peer):
+        return self._peer_map.get(peer, peer)
+
+    def _get_node_key(self, peer, client_config=None):
+        proto, addr = self._split_peer(peer)[:2]
+        node_id = getattr(client_config, "node_id", "").strip() if client_config is not None else ""
+        node_name = getattr(client_config, "name", "").strip() if client_config is not None else ""
+
+        if proto in ("ipv4", "ipv6"):
+            if node_id != "":
+                return f"node:{node_id}"
+            if node_name != "" and self.is_local(f"{proto}:{addr}"):
+                return f"node:{node_name}"
+
+        return f"{proto}:{addr}"
+
     def is_connected(self, addr):
         try:
             nd = self.get_node(addr)
@@ -249,6 +285,7 @@ class Nodes(QObject):

     def save_node_config(self, addr, config):
         try:
+            addr = self._resolve_node_key(addr)
             self._nodes[addr]['data'].config = config
         except Exception as e:
             print(self.LOG_TAG + " exception saving node config: ", e, addr, config)
@@ -287,6 +324,7 @@ class Nodes(QObject):

     def send_notification(self, addr, notification, callback_signal=None):
         try:
+            addr = self._resolve_node_key(addr)
             notification.id = int(str(time.time()).replace(".", ""))
             if addr not in self._nodes:
                 # FIXME: the reply is sent before we return the notification id
@@ -341,6 +379,7 @@ class Nodes(QObject):

     def reply_notification(self, addr, reply):
         try:
+            addr = self._resolve_node_key(addr)
             if reply == None:
                 print(self.LOG_TAG, " reply notification None")
                 return
@@ -375,8 +414,7 @@ class Nodes(QObject):

     def insert(self, peer, status=ONLINE):
         try:
-            proto, addr = self.get_addr(peer)
-            naddr = "{0}:{1}".format(proto, addr)
+            naddr = self._resolve_node_key(peer)
             self._db.insert(
                 "nodes",
                 "(addr, status, hostname, daemon_version, daemon_uptime, " \
@@ -390,8 +428,7 @@ class Nodes(QObject):

     def update(self, peer, status=ONLINE):
         try:
-            proto, addr = self.get_addr(peer)
-            naddr = "{0}:{1}".format(proto, addr)
+            naddr = self._resolve_node_key(peer)
             self._db.update("nodes",
                     "hostname=?,version=?,last_connection=?,status=?",
                     (
diff --git a/ui/opensnitch/proto/ui_pb2.py b/ui/opensnitch/proto/ui_pb2.py
index a864f586..965c7f72 100644
--- a/ui/opensnitch/proto/ui_pb2.py
+++ b/ui/opensnitch/proto/ui_pb2.py
@@ -2,9 +2,11 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: ui.proto
 """Generated protocol buffer code."""
-from google.protobuf.internal import builder as _builder
+from google.protobuf.internal import enum_type_wrapper
 from google.protobuf import descriptor as _descriptor
 from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import message as _message
+from google.protobuf import reflection as _reflection
 from google.protobuf import symbol_database as _symbol_database
 # @@protoc_insertion_point(imports)

@@ -13,10 +15,294 @@ _sym_db = _symbol_database.Default()



-DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x08ui.proto\x12\x08protocol\"\xcb\x04\n\x05\x41lert\x12\n\n\x02id\x18\x01 \x01(\x04\x12\"\n\x04type\x18\x02 \x01(\x0e\x32\x14.protocol.Alert.Type\x12&\n\x06\x61\x63tion\x18\x03 \x01(\x0e\x32\x16.protocol.Alert.Action\x12*\n\x08priority\x18\x04 \x01(\x0e\x32\x18.protocol.Alert.Priority\x12\"\n\x04what\x18\x05 \x01(\x0e\x32\x14.protocol.Alert.What\x12\x0e\n\x04text\x18\x06 \x01(\tH\x00\x12!\n\x04proc\x18\x08 \x01(\x0b\x32\x11.protocol.ProcessH\x00\x12$\n\x04\x63onn\x18\t \x01(\x0b\x32\x14.protocol.ConnectionH\x00\x12\x1e\n\x04rule\x18\n \x01(\x0b\x32\x0e.protocol.RuleH\x00\x12\"\n\x06\x66wrule\x18\x0b \x01(\x0b\x32\x10.protocol.FwRuleH\x00\")\n\x08Priority\x12\x07\n\x03LOW\x10\x00\x12\n\n\x06MEDIUM\x10\x01\x12\x08\n\x04HIGH\x10\x02\"(\n\x04Type\x12\t\n\x05\x45RROR\x10\x00\x12\x0b\n\x07WARNING\x10\x01\x12\x08\n\x04INFO\x10\x02\"2\n\x06\x41\x63tion\x12\x08\n\x04NONE\x10\x00\x12\x0e\n\nSHOW_ALERT\x10\x01\x12\x0e\n\nSAVE_TO_DB\x10\x02\"l\n\x04What\x12\x0b\n\x07GENERIC\x10\x00\x12\x10\n\x0cPROC_MONITOR\x10\x01\x12\x0c\n\x08\x46IREWALL\x10\x02\x12\x0e\n\nCONNECTION\x10\x03\x12\x08\n\x04RULE\x10\x04\x12\x0b\n\x07NETLINK\x10\x05\x12\x10\n\x0cKERNEL_EVENT\x10\x06\x42\x06\n\x04\x64\x61ta\"\x19\n\x0bMsgResponse\x12\n\n\x02id\x18\x01 \x01(\x04\"o\n\x05\x45vent\x12\x0c\n\x04time\x18\x01 \x01(\t\x12(\n\nconnection\x18\x02 \x01(\x0b\x32\x14.protocol.Connection\x12\x1c\n\x04rule\x18\x03 \x01(\x0b\x32\x0e.protocol.Rule\x12\x10\n\x08unixnano\x18\x04 \x01(\x03\"\xd3\x06\n\nStatistics\x12\x16\n\x0e\x64\x61\x65mon_version\x18\x01 \x01(\t\x12\r\n\x05rules\x18\x02 \x01(\x04\x12\x0e\n\x06uptime\x18\x03 \x01(\x04\x12\x15\n\rdns_responses\x18\x04 \x01(\x04\x12\x13\n\x0b\x63onnections\x18\x05 \x01(\x04\x12\x0f\n\x07ignored\x18\x06 \x01(\x04\x12\x10\n\x08\x61\x63\x63\x65pted\x18\x07 \x01(\x04\x12\x0f\n\x07\x64ropped\x18\x08 \x01(\x04\x12\x11\n\trule_hits\x18\t \x01(\x04\x12\x13\n\x0brule_misses\x18\n \x01(\x04\x12\x33\n\x08\x62y_proto\x18\x0b \x03(\x0b\x32!.protocol.Statistics.ByProtoEntry\x12\x37\n\nby_address\x18\x0c \x03(\x0b\x32#.protocol.Statistics.ByAddressEntry\x12\x31\n\x07\x62y_host\x18\r \x03(\x0b\x32 .protocol.Statistics.ByHostEntry\x12\x31\n\x07\x62y_port\x18\x0e \x03(\x0b\x32 .protocol.Statistics.ByPortEntry\x12/\n\x06\x62y_uid\x18\x0f \x03(\x0b\x32\x1f.protocol.Statistics.ByUidEntry\x12=\n\rby_executable\x18\x10 \x03(\x0b\x32&.protocol.Statistics.ByExecutableEntry\x12\x1f\n\x06\x65vents\x18\x11 \x03(\x0b\x32\x0f.protocol.Event\x1a.\n\x0c\x42yProtoEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a\x30\n\x0e\x42yAddressEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a-\n\x0b\x42yHostEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a-\n\x0b\x42yPortEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a,\n\nByUidEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a\x33\n\x11\x42yExecutableEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\">\n\x0bPingRequest\x12\n\n\x02id\x18\x01 \x01(\x04\x12#\n\x05stats\x18\x02 \x01(\x0b\x32\x14.protocol.Statistics\"\x17\n\tPingReply\x12\n\n\x02id\x18\x01 \x01(\x04\"\'\n\tStringInt\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r\"\x9b\x03\n\x07Process\x12\x0b\n\x03pid\x18\x01 \x01(\x04\x12\x0c\n\x04ppid\x18\x02 \x01(\x04\x12\x0b\n\x03uid\x18\x03 \x01(\x04\x12\x0c\n\x04\x63omm\x18\x04 \x01(\t\x12\x0c\n\x04path\x18\x05 \x01(\t\x12\x0c\n\x04\x61rgs\x18\x06 \x03(\t\x12\'\n\x03\x65nv\x18\x07 \x03(\x0b\x32\x1a.protocol.Process.EnvEntry\x12\x0b\n\x03\x63wd\x18\x08 \x01(\t\x12\x33\n\tchecksums\x18\t \x03(\x0b\x32 .protocol.Process.ChecksumsEntry\x12\x10\n\x08io_reads\x18\n \x01(\x04\x12\x11\n\tio_writes\x18\x0b \x01(\x04\x12\x11\n\tnet_reads\x18\x0c \x01(\x04\x12\x12\n\nnet_writes\x18\r \x01(\x04\x12)\n\x0cprocess_tree\x18\x0e \x03(\x0b\x32\x13.protocol.StringInt\x1a*\n\x08\x45nvEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x30\n\x0e\x43hecksumsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xf3\x03\n\nConnection\x12\x10\n\x08protocol\x18\x01 \x01(\t\x12\x0e\n\x06src_ip\x18\x02 \x01(\t\x12\x10\n\x08src_port\x18\x03 \x01(\r\x12\x0e\n\x06\x64st_ip\x18\x04 \x01(\t\x12\x10\n\x08\x64st_host\x18\x05 \x01(\t\x12\x10\n\x08\x64st_port\x18\x06 \x01(\r\x12\x0f\n\x07user_id\x18\x07 \x01(\r\x12\x12\n\nprocess_id\x18\x08 \x01(\r\x12\x14\n\x0cprocess_path\x18\t \x01(\t\x12\x13\n\x0bprocess_cwd\x18\n \x01(\t\x12\x14\n\x0cprocess_args\x18\x0b \x03(\t\x12\x39\n\x0bprocess_env\x18\x0c \x03(\x0b\x32$.protocol.Connection.ProcessEnvEntry\x12\x45\n\x11process_checksums\x18\r \x03(\x0b\x32*.protocol.Connection.ProcessChecksumsEntry\x12)\n\x0cprocess_tree\x18\x0e \x03(\x0b\x32\x13.protocol.StringInt\x1a\x31\n\x0fProcessEnvEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x37\n\x15ProcessChecksumsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"l\n\x08Operator\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0f\n\x07operand\x18\x02 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\t\x12\x11\n\tsensitive\x18\x04 \x01(\x08\x12 \n\x04list\x18\x05 \x03(\x0b\x32\x12.protocol.Operator\"\xb6\x01\n\x04Rule\x12\x0f\n\x07\x63reated\x18\x01 \x01(\x03\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x04 \x01(\x08\x12\x12\n\nprecedence\x18\x05 \x01(\x08\x12\r\n\x05nolog\x18\x06 \x01(\x08\x12\x0e\n\x06\x61\x63tion\x18\x07 \x01(\t\x12\x10\n\x08\x64uration\x18\x08 \x01(\t\x12$\n\x08operator\x18\t \x01(\x0b\x32\x12.protocol.Operator\"-\n\x0fStatementValues\x12\x0b\n\x03Key\x18\x01 \x01(\t\x12\r\n\x05Value\x18\x02 \x01(\t\"P\n\tStatement\x12\n\n\x02Op\x18\x01 \x01(\t\x12\x0c\n\x04Name\x18\x02 \x01(\t\x12)\n\x06Values\x18\x03 \x03(\x0b\x32\x19.protocol.StatementValues\"5\n\x0b\x45xpressions\x12&\n\tStatement\x18\x01 \x01(\x0b\x32\x13.protocol.Statement\"\xd6\x01\n\x06\x46wRule\x12\r\n\x05Table\x18\x01 \x01(\t\x12\r\n\x05\x43hain\x18\x02 \x01(\t\x12\x0c\n\x04UUID\x18\x03 \x01(\t\x12\x0f\n\x07\x45nabled\x18\x04 \x01(\x08\x12\x10\n\x08Position\x18\x05 \x01(\x04\x12\x13\n\x0b\x44\x65scription\x18\x06 \x01(\t\x12\x12\n\nParameters\x18\x07 \x01(\t\x12*\n\x0b\x45xpressions\x18\x08 \x03(\x0b\x32\x15.protocol.Expressions\x12\x0e\n\x06Target\x18\t \x01(\t\x12\x18\n\x10TargetParameters\x18\n \x01(\t\"\x95\x01\n\x07\x46wChain\x12\x0c\n\x04Name\x18\x01 \x01(\t\x12\r\n\x05Table\x18\x02 \x01(\t\x12\x0e\n\x06\x46\x61mily\x18\x03 \x01(\t\x12\x10\n\x08Priority\x18\x04 \x01(\t\x12\x0c\n\x04Type\x18\x05 \x01(\t\x12\x0c\n\x04Hook\x18\x06 \x01(\t\x12\x0e\n\x06Policy\x18\x07 \x01(\t\x12\x1f\n\x05Rules\x18\x08 \x03(\x0b\x32\x10.protocol.FwRule\"M\n\x08\x46wChains\x12\x1e\n\x04Rule\x18\x01 \x01(\x0b\x32\x10.protocol.FwRule\x12!\n\x06\x43hains\x18\x02 \x03(\x0b\x32\x11.protocol.FwChain\"X\n\x0bSysFirewall\x12\x0f\n\x07\x45nabled\x18\x01 \x01(\x08\x12\x0f\n\x07Version\x18\x02 \x01(\r\x12\'\n\x0bSystemRules\x18\x03 \x03(\x0b\x32\x12.protocol.FwChains\"\xc4\x01\n\x0c\x43lientConfig\x12\n\n\x02id\x18\x01 \x01(\x04\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0f\n\x07version\x18\x03 \x01(\t\x12\x19\n\x11isFirewallRunning\x18\x04 \x01(\x08\x12\x0e\n\x06\x63onfig\x18\x05 \x01(\t\x12\x10\n\x08logLevel\x18\x06 \x01(\r\x12\x1d\n\x05rules\x18\x07 \x03(\x0b\x32\x0e.protocol.Rule\x12-\n\x0esystemFirewall\x18\x08 \x01(\x0b\x32\x15.protocol.SysFirewall\"\xbb\x01\n\x0cNotification\x12\n\n\x02id\x18\x01 \x01(\x04\x12\x12\n\nclientName\x18\x02 \x01(\t\x12\x12\n\nserverName\x18\x03 \x01(\t\x12\x1e\n\x04type\x18\x04 \x01(\x0e\x32\x10.protocol.Action\x12\x0c\n\x04\x64\x61ta\x18\x05 \x01(\t\x12\x1d\n\x05rules\x18\x06 \x03(\x0b\x32\x0e.protocol.Rule\x12*\n\x0bsysFirewall\x18\x07 \x01(\x0b\x32\x15.protocol.SysFirewall\"\\\n\x11NotificationReply\x12\n\n\x02id\x18\x01 \x01(\x04\x12-\n\x04\x63ode\x18\x02 \x01(\x0e\x32\x1f.protocol.NotificationReplyCode\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\t*\x95\x02\n\x06\x41\x63tion\x12\x08\n\x04NONE\x10\x00\x12\x17\n\x13\x45NABLE_INTERCEPTION\x10\x01\x12\x18\n\x14\x44ISABLE_INTERCEPTION\x10\x02\x12\x13\n\x0f\x45NABLE_FIREWALL\x10\x03\x12\x14\n\x10\x44ISABLE_FIREWALL\x10\x04\x12\x13\n\x0fRELOAD_FW_RULES\x10\x05\x12\x11\n\rCHANGE_CONFIG\x10\x06\x12\x0f\n\x0b\x45NABLE_RULE\x10\x07\x12\x10\n\x0c\x44ISABLE_RULE\x10\x08\x12\x0f\n\x0b\x44\x45LETE_RULE\x10\t\x12\x0f\n\x0b\x43HANGE_RULE\x10\n\x12\r\n\tLOG_LEVEL\x10\x0b\x12\x08\n\x04STOP\x10\x0c\x12\x0e\n\nTASK_START\x10\r\x12\r\n\tTASK_STOP\x10\x0e**\n\x15NotificationReplyCode\x12\x06\n\x02OK\x10\x00\x12\t\n\x05\x45RROR\x10\x01\x32\xaf\x02\n\x02UI\x12\x34\n\x04Ping\x12\x15.protocol.PingRequest\x1a\x13.protocol.PingReply\"\x00\x12\x31\n\x07\x41skRule\x12\x14.protocol.Connection\x1a\x0e.protocol.Rule\"\x00\x12=\n\tSubscribe\x12\x16.protocol.ClientConfig\x1a\x16.protocol.ClientConfig\"\x00\x12J\n\rNotifications\x12\x1b.protocol.NotificationReply\x1a\x16.protocol.Notification\"\x00(\x01\x30\x01\x12\x35\n\tPostAlert\x12\x0f.protocol.Alert\x1a\x15.protocol.MsgResponse\"\x00\x42\x35Z3github.com/evilsocket/opensnitch/daemon/ui/protocolb\x06proto3')
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x08ui.proto\x12\x08protocol\"\xcb\x04\n\x05\x41lert\x12\n\n\x02id\x18\x01 \x01(\x04\x12\"\n\x04type\x18\x02 \x01(\x0e\x32\x14.protocol.Alert.Type\x12&\n\x06\x61\x63tion\x18\x03 \x01(\x0e\x32\x16.protocol.Alert.Action\x12*\n\x08priority\x18\x04 \x01(\x0e\x32\x18.protocol.Alert.Priority\x12\"\n\x04what\x18\x05 \x01(\x0e\x32\x14.protocol.Alert.What\x12\x0e\n\x04text\x18\x06 \x01(\tH\x00\x12!\n\x04proc\x18\x08 \x01(\x0b\x32\x11.protocol.ProcessH\x00\x12$\n\x04\x63onn\x18\t \x01(\x0b\x32\x14.protocol.ConnectionH\x00\x12\x1e\n\x04rule\x18\n \x01(\x0b\x32\x0e.protocol.RuleH\x00\x12\"\n\x06\x66wrule\x18\x0b \x01(\x0b\x32\x10.protocol.FwRuleH\x00\")\n\x08Priority\x12\x07\n\x03LOW\x10\x00\x12\n\n\x06MEDIUM\x10\x01\x12\x08\n\x04HIGH\x10\x02\"(\n\x04Type\x12\t\n\x05\x45RROR\x10\x00\x12\x0b\n\x07WARNING\x10\x01\x12\x08\n\x04INFO\x10\x02\"2\n\x06\x41\x63tion\x12\x08\n\x04NONE\x10\x00\x12\x0e\n\nSHOW_ALERT\x10\x01\x12\x0e\n\nSAVE_TO_DB\x10\x02\"l\n\x04What\x12\x0b\n\x07GENERIC\x10\x00\x12\x10\n\x0cPROC_MONITOR\x10\x01\x12\x0c\n\x08\x46IREWALL\x10\x02\x12\x0e\n\nCONNECTION\x10\x03\x12\x08\n\x04RULE\x10\x04\x12\x0b\n\x07NETLINK\x10\x05\x12\x10\n\x0cKERNEL_EVENT\x10\x06\x42\x06\n\x04\x64\x61ta\"\x19\n\x0bMsgResponse\x12\n\n\x02id\x18\x01 \x01(\x04\"o\n\x05\x45vent\x12\x0c\n\x04time\x18\x01 \x01(\t\x12(\n\nconnection\x18\x02 \x01(\x0b\x32\x14.protocol.Connection\x12\x1c\n\x04rule\x18\x03 \x01(\x0b\x32\x0e.protocol.Rule\x12\x10\n\x08unixnano\x18\x04 \x01(\x03\"\xd3\x06\n\nStatistics\x12\x16\n\x0e\x64\x61\x65mon_version\x18\x01 \x01(\t\x12\r\n\x05rules\x18\x02 \x01(\x04\x12\x0e\n\x06uptime\x18\x03 \x01(\x04\x12\x15\n\rdns_responses\x18\x04 \x01(\x04\x12\x13\n\x0b\x63onnections\x18\x05 \x01(\x04\x12\x0f\n\x07ignored\x18\x06 \x01(\x04\x12\x10\n\x08\x61\x63\x63\x65pted\x18\x07 \x01(\x04\x12\x0f\n\x07\x64ropped\x18\x08 \x01(\x04\x12\x11\n\trule_hits\x18\t \x01(\x04\x12\x13\n\x0brule_misses\x18\n \x01(\x04\x12\x33\n\x08\x62y_proto\x18\x0b \x03(\x0b\x32!.protocol.Statistics.ByProtoEntry\x12\x37\n\nby_address\x18\x0c \x03(\x0b\x32#.protocol.Statistics.ByAddressEntry\x12\x31\n\x07\x62y_host\x18\r \x03(\x0b\x32 .protocol.Statistics.ByHostEntry\x12\x31\n\x07\x62y_port\x18\x0e \x03(\x0b\x32 .protocol.Statistics.ByPortEntry\x12/\n\x06\x62y_uid\x18\x0f \x03(\x0b\x32\x1f.protocol.Statistics.ByUidEntry\x12=\n\rby_executable\x18\x10 \x03(\x0b\x32&.protocol.Statistics.ByExecutableEntry\x12\x1f\n\x06\x65vents\x18\x11 \x03(\x0b\x32\x0f.protocol.Event\x1a.\n\x0c\x42yProtoEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a\x30\n\x0e\x42yAddressEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a-\n\x0b\x42yHostEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a-\n\x0b\x42yPortEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a,\n\nByUidEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a\x33\n\x11\x42yExecutableEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\">\n\x0bPingRequest\x12\n\n\x02id\x18\x01 \x01(\x04\x12#\n\x05stats\x18\x02 \x01(\x0b\x32\x14.protocol.Statistics\"\x17\n\tPingReply\x12\n\n\x02id\x18\x01 \x01(\x04\"\'\n\tStringInt\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r\"\x9b\x03\n\x07Process\x12\x0b\n\x03pid\x18\x01 \x01(\x04\x12\x0c\n\x04ppid\x18\x02 \x01(\x04\x12\x0b\n\x03uid\x18\x03 \x01(\x04\x12\x0c\n\x04\x63omm\x18\x04 \x01(\t\x12\x0c\n\x04path\x18\x05 \x01(\t\x12\x0c\n\x04\x61rgs\x18\x06 \x03(\t\x12\'\n\x03\x65nv\x18\x07 \x03(\x0b\x32\x1a.protocol.Process.EnvEntry\x12\x0b\n\x03\x63wd\x18\x08 \x01(\t\x12\x33\n\tchecksums\x18\t \x03(\x0b\x32 .protocol.Process.ChecksumsEntry\x12\x10\n\x08io_reads\x18\n \x01(\x04\x12\x11\n\tio_writes\x18\x0b \x01(\x04\x12\x11\n\tnet_reads\x18\x0c \x01(\x04\x12\x12\n\nnet_writes\x18\r \x01(\x04\x12)\n\x0cprocess_tree\x18\x0e \x03(\x0b\x32\x13.protocol.StringInt\x1a*\n\x08\x45nvEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x30\n\x0e\x43hecksumsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xf3\x03\n\nConnection\x12\x10\n\x08protocol\x18\x01 \x01(\t\x12\x0e\n\x06src_ip\x18\x02 \x01(\t\x12\x10\n\x08src_port\x18\x03 \x01(\r\x12\x0e\n\x06\x64st_ip\x18\x04 \x01(\t\x12\x10\n\x08\x64st_host\x18\x05 \x01(\t\x12\x10\n\x08\x64st_port\x18\x06 \x01(\r\x12\x0f\n\x07user_id\x18\x07 \x01(\r\x12\x12\n\nprocess_id\x18\x08 \x01(\r\x12\x14\n\x0cprocess_path\x18\t \x01(\t\x12\x13\n\x0bprocess_cwd\x18\n \x01(\t\x12\x14\n\x0cprocess_args\x18\x0b \x03(\t\x12\x39\n\x0bprocess_env\x18\x0c \x03(\x0b\x32$.protocol.Connection.ProcessEnvEntry\x12\x45\n\x11process_checksums\x18\r \x03(\x0b\x32*.protocol.Connection.ProcessChecksumsEntry\x12)\n\x0cprocess_tree\x18\x0e \x03(\x0b\x32\x13.protocol.StringInt\x1a\x31\n\x0fProcessEnvEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x37\n\x15ProcessChecksumsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"l\n\x08Operator\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0f\n\x07operand\x18\x02 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\t\x12\x11\n\tsensitive\x18\x04 \x01(\x08\x12 \n\x04list\x18\x05 \x03(\x0b\x32\x12.protocol.Operator\"\xb6\x01\n\x04Rule\x12\x0f\n\x07\x63reated\x18\x01 \x01(\x03\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x04 \x01(\x08\x12\x12\n\nprecedence\x18\x05 \x01(\x08\x12\r\n\x05nolog\x18\x06 \x01(\x08\x12\x0e\n\x06\x61\x63tion\x18\x07 \x01(\t\x12\x10\n\x08\x64uration\x18\x08 \x01(\t\x12$\n\x08operator\x18\t \x01(\x0b\x32\x12.protocol.Operator\"-\n\x0fStatementValues\x12\x0b\n\x03Key\x18\x01 \x01(\t\x12\r\n\x05Value\x18\x02 \x01(\t\"P\n\tStatement\x12\n\n\x02Op\x18\x01 \x01(\t\x12\x0c\n\x04Name\x18\x02 \x01(\t\x12)\n\x06Values\x18\x03 \x03(\x0b\x32\x19.protocol.StatementValues\"5\n\x0b\x45xpressions\x12&\n\tStatement\x18\x01 \x01(\x0b\x32\x13.protocol.Statement\"\xd6\x01\n\x06\x46wRule\x12\r\n\x05Table\x18\x01 \x01(\t\x12\r\n\x05\x43hain\x18\x02 \x01(\t\x12\x0c\n\x04UUID\x18\x03 \x01(\t\x12\x0f\n\x07\x45nabled\x18\x04 \x01(\x08\x12\x10\n\x08Position\x18\x05 \x01(\x04\x12\x13\n\x0b\x44\x65scription\x18\x06 \x01(\t\x12\x12\n\nParameters\x18\x07 \x01(\t\x12*\n\x0b\x45xpressions\x18\x08 \x03(\x0b\x32\x15.protocol.Expressions\x12\x0e\n\x06Target\x18\t \x01(\t\x12\x18\n\x10TargetParameters\x18\n \x01(\t\"\x95\x01\n\x07\x46wChain\x12\x0c\n\x04Name\x18\x01 \x01(\t\x12\r\n\x05Table\x18\x02 \x01(\t\x12\x0e\n\x06\x46\x61mily\x18\x03 \x01(\t\x12\x10\n\x08Priority\x18\x04 \x01(\t\x12\x0c\n\x04Type\x18\x05 \x01(\t\x12\x0c\n\x04Hook\x18\x06 \x01(\t\x12\x0e\n\x06Policy\x18\x07 \x01(\t\x12\x1f\n\x05Rules\x18\x08 \x03(\x0b\x32\x10.protocol.FwRule\"M\n\x08\x46wChains\x12\x1e\n\x04Rule\x18\x01 \x01(\x0b\x32\x10.protocol.FwRule\x12!\n\x06\x43hains\x18\x02 \x03(\x0b\x32\x11.protocol.FwChain\"X\n\x0bSysFirewall\x12\x0f\n\x07\x45nabled\x18\x01 \x01(\x08\x12\x0f\n\x07Version\x18\x02 \x01(\r\x12\'\n\x0bSystemRules\x18\x03 \x03(\x0b\x32\x12.protocol.FwChains\"\xd5\x01\n\x0c\x43lientConfig\x12\n\n\x02id\x18\x01 \x01(\x04\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0f\n\x07version\x18\x03 \x01(\t\x12\x19\n\x11isFirewallRunning\x18\x04 \x01(\x08\x12\x0e\n\x06\x63onfig\x18\x05 \x01(\t\x12\x10\n\x08logLevel\x18\x06 \x01(\r\x12\x1d\n\x05rules\x18\x07 \x03(\x0b\x32\x0e.protocol.Rule\x12-\n\x0esystemFirewall\x18\x08 \x01(\x0b\x32\x15.protocol.SysFirewall\x12\x0f\n\x07node_id\x18\t \x01(\t\"\xbb\x01\n\x0cNotification\x12\n\n\x02id\x18\x01 \x01(\x04\x12\x12\n\nclientName\x18\x02 \x01(\t\x12\x12\n\nserverName\x18\x03 \x01(\t\x12\x1e\n\x04type\x18\x04 \x01(\x0e\x32\x10.protocol.Action\x12\x0c\n\x04\x64\x61ta\x18\x05 \x01(\t\x12\x1d\n\x05rules\x18\x06 \x03(\x0b\x32\x0e.protocol.Rule\x12*\n\x0bsysFirewall\x18\x07 \x01(\x0b\x32\x15.protocol.SysFirewall\"\\\n\x11NotificationReply\x12\n\n\x02id\x18\x01 \x01(\x04\x12-\n\x04\x63ode\x18\x02 \x01(\x0e\x32\x1f.protocol.NotificationReplyCode\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\t*\x95\x02\n\x06\x41\x63tion\x12\x08\n\x04NONE\x10\x00\x12\x17\n\x13\x45NABLE_INTERCEPTION\x10\x01\x12\x18\n\x14\x44ISABLE_INTERCEPTION\x10\x02\x12\x13\n\x0f\x45NABLE_FIREWALL\x10\x03\x12\x14\n\x10\x44ISABLE_FIREWALL\x10\x04\x12\x13\n\x0fRELOAD_FW_RULES\x10\x05\x12\x11\n\rCHANGE_CONFIG\x10\x06\x12\x0f\n\x0b\x45NABLE_RULE\x10\x07\x12\x10\n\x0c\x44ISABLE_RULE\x10\x08\x12\x0f\n\x0b\x44\x45LETE_RULE\x10\t\x12\x0f\n\x0b\x43HANGE_RULE\x10\n\x12\r\n\tLOG_LEVEL\x10\x0b\x12\x08\n\x04STOP\x10\x0c\x12\x0e\n\nTASK_START\x10\r\x12\r\n\tTASK_STOP\x10\x0e**\n\x15NotificationReplyCode\x12\x06\n\x02OK\x10\x00\x12\t\n\x05\x45RROR\x10\x01\x32\xaf\x02\n\x02UI\x12\x34\n\x04Ping\x12\x15.protocol.PingRequest\x1a\x13.protocol.PingReply\"\x00\x12\x31\n\x07\x41skRule\x12\x14.protocol.Connection\x1a\x0e.protocol.Rule\"\x00\x12=\n\tSubscribe\x12\x16.protocol.ClientConfig\x1a\x16.protocol.ClientConfig\"\x00\x12J\n\rNotifications\x12\x1b.protocol.NotificationReply\x1a\x16.protocol.Notification\"\x00(\x01\x30\x01\x12\x35\n\tPostAlert\x12\x0f.protocol.Alert\x1a\x15.protocol.MsgResponse\"\x00\x42\x35Z3github.com/evilsocket/opensnitch/daemon/ui/protocolb\x06proto3')

-_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
-_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ui_pb2', globals())
+_ACTION = DESCRIPTOR.enum_types_by_name['Action']
+Action = enum_type_wrapper.EnumTypeWrapper(_ACTION)
+_NOTIFICATIONREPLYCODE = DESCRIPTOR.enum_types_by_name['NotificationReplyCode']
+NotificationReplyCode = enum_type_wrapper.EnumTypeWrapper(_NOTIFICATIONREPLYCODE)
+NONE = 0
+ENABLE_INTERCEPTION = 1
+DISABLE_INTERCEPTION = 2
+ENABLE_FIREWALL = 3
+DISABLE_FIREWALL = 4
+RELOAD_FW_RULES = 5
+CHANGE_CONFIG = 6
+ENABLE_RULE = 7
+DISABLE_RULE = 8
+DELETE_RULE = 9
+CHANGE_RULE = 10
+LOG_LEVEL = 11
+STOP = 12
+TASK_START = 13
+TASK_STOP = 14
+OK = 0
+ERROR = 1
+
+
+_ALERT = DESCRIPTOR.message_types_by_name['Alert']
+_MSGRESPONSE = DESCRIPTOR.message_types_by_name['MsgResponse']
+_EVENT = DESCRIPTOR.message_types_by_name['Event']
+_STATISTICS = DESCRIPTOR.message_types_by_name['Statistics']
+_STATISTICS_BYPROTOENTRY = _STATISTICS.nested_types_by_name['ByProtoEntry']
+_STATISTICS_BYADDRESSENTRY = _STATISTICS.nested_types_by_name['ByAddressEntry']
+_STATISTICS_BYHOSTENTRY = _STATISTICS.nested_types_by_name['ByHostEntry']
+_STATISTICS_BYPORTENTRY = _STATISTICS.nested_types_by_name['ByPortEntry']
+_STATISTICS_BYUIDENTRY = _STATISTICS.nested_types_by_name['ByUidEntry']
+_STATISTICS_BYEXECUTABLEENTRY = _STATISTICS.nested_types_by_name['ByExecutableEntry']
+_PINGREQUEST = DESCRIPTOR.message_types_by_name['PingRequest']
+_PINGREPLY = DESCRIPTOR.message_types_by_name['PingReply']
+_STRINGINT = DESCRIPTOR.message_types_by_name['StringInt']
+_PROCESS = DESCRIPTOR.message_types_by_name['Process']
+_PROCESS_ENVENTRY = _PROCESS.nested_types_by_name['EnvEntry']
+_PROCESS_CHECKSUMSENTRY = _PROCESS.nested_types_by_name['ChecksumsEntry']
+_CONNECTION = DESCRIPTOR.message_types_by_name['Connection']
+_CONNECTION_PROCESSENVENTRY = _CONNECTION.nested_types_by_name['ProcessEnvEntry']
+_CONNECTION_PROCESSCHECKSUMSENTRY = _CONNECTION.nested_types_by_name['ProcessChecksumsEntry']
+_OPERATOR = DESCRIPTOR.message_types_by_name['Operator']
+_RULE = DESCRIPTOR.message_types_by_name['Rule']
+_STATEMENTVALUES = DESCRIPTOR.message_types_by_name['StatementValues']
+_STATEMENT = DESCRIPTOR.message_types_by_name['Statement']
+_EXPRESSIONS = DESCRIPTOR.message_types_by_name['Expressions']
+_FWRULE = DESCRIPTOR.message_types_by_name['FwRule']
+_FWCHAIN = DESCRIPTOR.message_types_by_name['FwChain']
+_FWCHAINS = DESCRIPTOR.message_types_by_name['FwChains']
+_SYSFIREWALL = DESCRIPTOR.message_types_by_name['SysFirewall']
+_CLIENTCONFIG = DESCRIPTOR.message_types_by_name['ClientConfig']
+_NOTIFICATION = DESCRIPTOR.message_types_by_name['Notification']
+_NOTIFICATIONREPLY = DESCRIPTOR.message_types_by_name['NotificationReply']
+_ALERT_PRIORITY = _ALERT.enum_types_by_name['Priority']
+_ALERT_TYPE = _ALERT.enum_types_by_name['Type']
+_ALERT_ACTION = _ALERT.enum_types_by_name['Action']
+_ALERT_WHAT = _ALERT.enum_types_by_name['What']
+Alert = _reflection.GeneratedProtocolMessageType('Alert', (_message.Message,), {
+  'DESCRIPTOR' : _ALERT,
+  '__module__' : 'ui_pb2'
+  # @@protoc_insertion_point(class_scope:protocol.Alert)
+  })
+_sym_db.RegisterMessage(Alert)
+
+MsgResponse = _reflection.GeneratedProtocolMessageType('MsgResponse', (_message.Message,), {
+  'DESCRIPTOR' : _MSGRESPONSE,
+  '__module__' : 'ui_pb2'
+  # @@protoc_insertion_point(class_scope:protocol.MsgResponse)
+  })
+_sym_db.RegisterMessage(MsgResponse)
+
+Event = _reflection.GeneratedProtocolMessageType('Event', (_message.Message,), {
+  'DESCRIPTOR' : _EVENT,
+  '__module__' : 'ui_pb2'
+  # @@protoc_insertion_point(class_scope:protocol.Event)
+  })
+_sym_db.RegisterMessage(Event)
+
+Statistics = _reflection.GeneratedProtocolMessageType('Statistics', (_message.Message,), {
+
+  'ByProtoEntry' : _reflection.GeneratedProtocolMessageType('ByProtoEntry', (_message.Message,), {
+    'DESCRIPTOR' : _STATISTICS_BYPROTOENTRY,
+    '__module__' : 'ui_pb2'
+    # @@protoc_insertion_point(class_scope:protocol.Statistics.ByProtoEntry)
+    })
+  ,
+
+  'ByAddressEntry' : _reflection.GeneratedProtocolMessageType('ByAddressEntry', (_message.Message,), {
+    'DESCRIPTOR' : _STATISTICS_BYADDRESSENTRY,
+    '__module__' : 'ui_pb2'
+    # @@protoc_insertion_point(class_scope:protocol.Statistics.ByAddressEntry)
+    })
+  ,
+
+  'ByHostEntry' : _reflection.GeneratedProtocolMessageType('ByHostEntry', (_message.Message,), {
+    'DESCRIPTOR' : _STATISTICS_BYHOSTENTRY,
+    '__module__' : 'ui_pb2'
+    # @@protoc_insertion_point(class_scope:protocol.Statistics.ByHostEntry)
+    })
+  ,
+
+  'ByPortEntry' : _reflection.GeneratedProtocolMessageType('ByPortEntry', (_message.Message,), {
+    'DESCRIPTOR' : _STATISTICS_BYPORTENTRY,
+    '__module__' : 'ui_pb2'
+    # @@protoc_insertion_point(class_scope:protocol.Statistics.ByPortEntry)
+    })
+  ,
+
+  'ByUidEntry' : _reflection.GeneratedProtocolMessageType('ByUidEntry', (_message.Message,), {
+    'DESCRIPTOR' : _STATISTICS_BYUIDENTRY,
+    '__module__' : 'ui_pb2'
+    # @@protoc_insertion_point(class_scope:protocol.Statistics.ByUidEntry)
+    })
+  ,
+
+  'ByExecutableEntry' : _reflection.GeneratedProtocolMessageType('ByExecutableEntry', (_message.Message,), {
+    'DESCRIPTOR' : _STATISTICS_BYEXECUTABLEENTRY,
+    '__module__' : 'ui_pb2'
+    # @@protoc_insertion_point(class_scope:protocol.Statistics.ByExecutableEntry)
+    })
+  ,
+  'DESCRIPTOR' : _STATISTICS,
+  '__module__' : 'ui_pb2'
+  # @@protoc_insertion_point(class_scope:protocol.Statistics)
+  })
+_sym_db.RegisterMessage(Statistics)
+_sym_db.RegisterMessage(Statistics.ByProtoEntry)
+_sym_db.RegisterMessage(Statistics.ByAddressEntry)
+_sym_db.RegisterMessage(Statistics.ByHostEntry)
+_sym_db.RegisterMessage(Statistics.ByPortEntry)
+_sym_db.RegisterMessage(Statistics.ByUidEntry)
+_sym_db.RegisterMessage(Statistics.ByExecutableEntry)
+
+PingRequest = _reflection.GeneratedProtocolMessageType('PingRequest', (_message.Message,), {
+  'DESCRIPTOR' : _PINGREQUEST,
+  '__module__' : 'ui_pb2'
+  # @@protoc_insertion_point(class_scope:protocol.PingRequest)
+  })
+_sym_db.RegisterMessage(PingRequest)
+
+PingReply = _reflection.GeneratedProtocolMessageType('PingReply', (_message.Message,), {
+  'DESCRIPTOR' : _PINGREPLY,
+  '__module__' : 'ui_pb2'
+  # @@protoc_insertion_point(class_scope:protocol.PingReply)
+  })
+_sym_db.RegisterMessage(PingReply)
+
+StringInt = _reflection.GeneratedProtocolMessageType('StringInt', (_message.Message,), {
+  'DESCRIPTOR' : _STRINGINT,
+  '__module__' : 'ui_pb2'
+  # @@protoc_insertion_point(class_scope:protocol.StringInt)
+  })
+_sym_db.RegisterMessage(StringInt)
+
+Process = _reflection.GeneratedProtocolMessageType('Process', (_message.Message,), {
+
+  'EnvEntry' : _reflection.GeneratedProtocolMessageType('EnvEntry', (_message.Message,), {
+    'DESCRIPTOR' : _PROCESS_ENVENTRY,
+    '__module__' : 'ui_pb2'
+    # @@protoc_insertion_point(class_scope:protocol.Process.EnvEntry)
+    })
+  ,
+
+  'ChecksumsEntry' : _reflection.GeneratedProtocolMessageType('ChecksumsEntry', (_message.Message,), {
+    'DESCRIPTOR' : _PROCESS_CHECKSUMSENTRY,
+    '__module__' : 'ui_pb2'
+    # @@protoc_insertion_point(class_scope:protocol.Process.ChecksumsEntry)
+    })
+  ,
+  'DESCRIPTOR' : _PROCESS,
+  '__module__' : 'ui_pb2'
+  # @@protoc_insertion_point(class_scope:protocol.Process)
+  })
+_sym_db.RegisterMessage(Process)
+_sym_db.RegisterMessage(Process.EnvEntry)
+_sym_db.RegisterMessage(Process.ChecksumsEntry)
+
+Connection = _reflection.GeneratedProtocolMessageType('Connection', (_message.Message,), {
+
+  'ProcessEnvEntry' : _reflection.GeneratedProtocolMessageType('ProcessEnvEntry', (_message.Message,), {
+    'DESCRIPTOR' : _CONNECTION_PROCESSENVENTRY,
+    '__module__' : 'ui_pb2'
+    # @@protoc_insertion_point(class_scope:protocol.Connection.ProcessEnvEntry)
+    })
+  ,
+
+  'ProcessChecksumsEntry' : _reflection.GeneratedProtocolMessageType('ProcessChecksumsEntry', (_message.Message,), {
+    'DESCRIPTOR' : _CONNECTION_PROCESSCHECKSUMSENTRY,
+    '__module__' : 'ui_pb2'
+    # @@protoc_insertion_point(class_scope:protocol.Connection.ProcessChecksumsEntry)
+    })
+  ,
+  'DESCRIPTOR' : _CONNECTION,
+  '__module__' : 'ui_pb2'
+  # @@protoc_insertion_point(class_scope:protocol.Connection)
+  })
+_sym_db.RegisterMessage(Connection)
+_sym_db.RegisterMessage(Connection.ProcessEnvEntry)
+_sym_db.RegisterMessage(Connection.ProcessChecksumsEntry)
+
+Operator = _reflection.GeneratedProtocolMessageType('Operator', (_message.Message,), {
+  'DESCRIPTOR' : _OPERATOR,
+  '__module__' : 'ui_pb2'
+  # @@protoc_insertion_point(class_scope:protocol.Operator)
+  })
+_sym_db.RegisterMessage(Operator)
+
+Rule = _reflection.GeneratedProtocolMessageType('Rule', (_message.Message,), {
+  'DESCRIPTOR' : _RULE,
+  '__module__' : 'ui_pb2'
+  # @@protoc_insertion_point(class_scope:protocol.Rule)
+  })
+_sym_db.RegisterMessage(Rule)
+
+StatementValues = _reflection.GeneratedProtocolMessageType('StatementValues', (_message.Message,), {
+  'DESCRIPTOR' : _STATEMENTVALUES,
+  '__module__' : 'ui_pb2'
+  # @@protoc_insertion_point(class_scope:protocol.StatementValues)
+  })
+_sym_db.RegisterMessage(StatementValues)
+
+Statement = _reflection.GeneratedProtocolMessageType('Statement', (_message.Message,), {
+  'DESCRIPTOR' : _STATEMENT,
+  '__module__' : 'ui_pb2'
+  # @@protoc_insertion_point(class_scope:protocol.Statement)
+  })
+_sym_db.RegisterMessage(Statement)
+
+Expressions = _reflection.GeneratedProtocolMessageType('Expressions', (_message.Message,), {
+  'DESCRIPTOR' : _EXPRESSIONS,
+  '__module__' : 'ui_pb2'
+  # @@protoc_insertion_point(class_scope:protocol.Expressions)
+  })
+_sym_db.RegisterMessage(Expressions)
+
+FwRule = _reflection.GeneratedProtocolMessageType('FwRule', (_message.Message,), {
+  'DESCRIPTOR' : _FWRULE,
+  '__module__' : 'ui_pb2'
+  # @@protoc_insertion_point(class_scope:protocol.FwRule)
+  })
+_sym_db.RegisterMessage(FwRule)
+
+FwChain = _reflection.GeneratedProtocolMessageType('FwChain', (_message.Message,), {
+  'DESCRIPTOR' : _FWCHAIN,
+  '__module__' : 'ui_pb2'
+  # @@protoc_insertion_point(class_scope:protocol.FwChain)
+  })
+_sym_db.RegisterMessage(FwChain)
+
+FwChains = _reflection.GeneratedProtocolMessageType('FwChains', (_message.Message,), {
+  'DESCRIPTOR' : _FWCHAINS,
+  '__module__' : 'ui_pb2'
+  # @@protoc_insertion_point(class_scope:protocol.FwChains)
+  })
+_sym_db.RegisterMessage(FwChains)
+
+SysFirewall = _reflection.GeneratedProtocolMessageType('SysFirewall', (_message.Message,), {
+  'DESCRIPTOR' : _SYSFIREWALL,
+  '__module__' : 'ui_pb2'
+  # @@protoc_insertion_point(class_scope:protocol.SysFirewall)
+  })
+_sym_db.RegisterMessage(SysFirewall)
+
+ClientConfig = _reflection.GeneratedProtocolMessageType('ClientConfig', (_message.Message,), {
+  'DESCRIPTOR' : _CLIENTCONFIG,
+  '__module__' : 'ui_pb2'
+  # @@protoc_insertion_point(class_scope:protocol.ClientConfig)
+  })
+_sym_db.RegisterMessage(ClientConfig)
+
+Notification = _reflection.GeneratedProtocolMessageType('Notification', (_message.Message,), {
+  'DESCRIPTOR' : _NOTIFICATION,
+  '__module__' : 'ui_pb2'
+  # @@protoc_insertion_point(class_scope:protocol.Notification)
+  })
+_sym_db.RegisterMessage(Notification)
+
+NotificationReply = _reflection.GeneratedProtocolMessageType('NotificationReply', (_message.Message,), {
+  'DESCRIPTOR' : _NOTIFICATIONREPLY,
+  '__module__' : 'ui_pb2'
+  # @@protoc_insertion_point(class_scope:protocol.NotificationReply)
+  })
+_sym_db.RegisterMessage(NotificationReply)
+
+_UI = DESCRIPTOR.services_by_name['UI']
 if _descriptor._USE_C_DESCRIPTORS == False:

   DESCRIPTOR._options = None
@@ -41,10 +327,10 @@ if _descriptor._USE_C_DESCRIPTORS == False:
   _CONNECTION_PROCESSENVENTRY._serialized_options = b'8\001'
   _CONNECTION_PROCESSCHECKSUMSENTRY._options = None
   _CONNECTION_PROCESSCHECKSUMSENTRY._serialized_options = b'8\001'
-  _ACTION._serialized_start=4153
-  _ACTION._serialized_end=4430
-  _NOTIFICATIONREPLYCODE._serialized_start=4432
-  _NOTIFICATIONREPLYCODE._serialized_end=4474
+  _ACTION._serialized_start=4170
+  _ACTION._serialized_end=4447
+  _NOTIFICATIONREPLYCODE._serialized_start=4449
+  _NOTIFICATIONREPLYCODE._serialized_end=4491
   _ALERT._serialized_start=23
   _ALERT._serialized_end=610
   _ALERT_PRIORITY._serialized_start=357
@@ -110,11 +396,11 @@ if _descriptor._USE_C_DESCRIPTORS == False:
   _SYSFIREWALL._serialized_start=3579
   _SYSFIREWALL._serialized_end=3667
   _CLIENTCONFIG._serialized_start=3670
-  _CLIENTCONFIG._serialized_end=3866
-  _NOTIFICATION._serialized_start=3869
-  _NOTIFICATION._serialized_end=4056
-  _NOTIFICATIONREPLY._serialized_start=4058
-  _NOTIFICATIONREPLY._serialized_end=4150
-  _UI._serialized_start=4477
-  _UI._serialized_end=4780
+  _CLIENTCONFIG._serialized_end=3883
+  _NOTIFICATION._serialized_start=3886
+  _NOTIFICATION._serialized_end=4073
+  _NOTIFICATIONREPLY._serialized_start=4075
+  _NOTIFICATIONREPLY._serialized_end=4167
+  _UI._serialized_start=4494
+  _UI._serialized_end=4797
 # @@protoc_insertion_point(module_scope)
diff --git a/ui/opensnitch/service.py b/ui/opensnitch/service.py
index eb3b53ab..9d91a58c 100644
--- a/ui/opensnitch/service.py
+++ b/ui/opensnitch/service.py
@@ -831,7 +831,8 @@ class UIService(ui_pb2_grpc.UIServicer, QtWidgets.QGraphicsObject):
                 ost.start()

         elif kwargs['action'] == self.DELETE_RULE:
-            self._db.delete_rule(kwargs['name'], kwargs['addr'])
+            proto, addr = self._get_peer(kwargs['addr'])
+            self._db.delete_rule(kwargs['name'], f"{proto}:{addr}")

         elif kwargs['action'] == self.NODE_DELETE:
             self._delete_node(kwargs['peer'])
@@ -980,6 +981,10 @@ class UIService(ui_pb2_grpc.UIServicer, QtWidgets.QGraphicsObject):

         stop_event = Event()
         def _on_client_closed():
+            prev_node = self._nodes.get_node(node_addr)
+            if prev_node is not None and prev_node.get('session', {}).get('peer') != local_peer:
+                return
+
             stop_event.set()
             print(datetime.now(), "[Notifications] client closed", context.peer())
             self._nodes.stop_notifications(node_addr)
@@ -1022,7 +1027,7 @@ class UIService(ui_pb2_grpc.UIServicer, QtWidgets.QGraphicsObject):
                     if in_message == None:
                         continue

-                    self._nodes.reply_notification(addr, in_message)
+                    self._nodes.reply_notification(node_addr, in_message)
                 except StopIteration:
                     print("[Notifications] Node {0} exited".format(addr))
                     break
-- 
2.53.0

3. Clone and Patch the Repository

We'll clone the official v1.8.0 repository and apply our patches.

# Clone the repository
git clone https://github.com/evilsocket/opensnitch.git
cd opensnitch

# Switch to the v1.8.0 branch
git checkout v1.8.0

# apply PR #1578
git am ../0001-v1.8.0-ui-use-node_id-as-canonical-remote-node-identity.patch

# apply the Fedora fix
git am ../0002-v1.8.0-local-fedora-rpm-build-fixes.patch

4. Setup the Build Directory and Archive Sources

Set up the standard RPM build directories, then package up the patched source code.

# Create RPM directories
mkdir -p ~/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}

# Archive the daemon source
git archive \
  --format=tar.gz \
  --prefix=opensnitch-1.8.0/ \
  HEAD \
  > ~/rpmbuild/SOURCES/opensnitch_1.8.0.orig.tar.gz

# Archive the UI source
git archive \
  --format=tar.gz \
  --prefix=opensnitch-ui-1.8.0/ \
  HEAD:ui \
  > ~/rpmbuild/SOURCES/opensnitch-ui-1.8.0.tar.gz

# Copy the patched spec files
cp utils/packaging/daemon/rpm/opensnitch.spec ~/rpmbuild/SPECS/
cp utils/packaging/ui/rpm/opensnitch-ui.spec ~/rpmbuild/SPECS/

5. Build the RPMs

Now, build your RPMs.

# Build the daemon RPM
rpmbuild -ba --define "_topdir $HOME/rpmbuild" ~/rpmbuild/SPECS/opensnitch.spec

# Build the UI RPM
rpmbuild -ba --define "_topdir $HOME/rpmbuild" ~/rpmbuild/SPECS/opensnitch-ui.spec

Once finished, your compiled RPMs will be waiting in ~/rpmbuild/RPMS/. Install them in your respective templates/AppVMs, configure your nodes, and you're good to go!