feat: F4.6g3 a computer's firewall window, measured against Java's with traffic from two networks

The firewall-pc scenario and FirewallWindowRun use Java's window as a person
does and send a ping, a TCP connection and a DNS question from the server's
network and from behind the router after each step. The core adds and
removes port rules (personalFirewall.ts) and writes both into the firewall's
log, which now carries each line's time; the room takes the window's
actions and sends its view and the log as lines; the editor shows Java's
window with its two tabs. Not adopted from Java: any integer as a port,
a port after a space refused without a word, a log one can type into.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-03 21:18:05 +00:00
co-authored by Claude Opus 5.5
parent 065b42430d
commit 2b85e7432c
25 changed files with 2092 additions and 19 deletions
+620
View File
@@ -0,0 +1,620 @@
{
"steps": [
{
"step": "open",
"traffic": {
"local": {
"ping": "ICMP 0/0 from 10.0.0.10",
"tcp": "TimeOutException: Zeitüberschreitung beim Verbindungsaufbau",
"dns": "TimeOutException"
},
"remote": {
"ping": "ICMP 0/0 from 10.0.0.10",
"tcp": "TimeOutException: Zeitüberschreitung beim Verbindungsaufbau",
"dns": "TimeOutException"
}
},
"active": {
"selected": true,
"enabled": true
},
"icmp": {
"selected": true,
"enabled": true
},
"udp": {
"selected": true,
"enabled": true
},
"port": "",
"protocol": "TCP",
"sender": "Alle Absender",
"rows": [],
"log": "",
"logEditable": true
},
{
"step": "add port abc",
"active": {
"selected": true,
"enabled": true
},
"icmp": {
"selected": true,
"enabled": true
},
"udp": {
"selected": true,
"enabled": true
},
"port": "abc",
"protocol": "TCP",
"sender": "Alle Absender",
"rows": [],
"log": "",
"logEditable": true
},
{
"step": "add an empty port",
"active": {
"selected": true,
"enabled": true
},
"icmp": {
"selected": true,
"enabled": true
},
"udp": {
"selected": true,
"enabled": true
},
"port": "",
"protocol": "TCP",
"sender": "Alle Absender",
"rows": [],
"log": "",
"logEditable": true
},
{
"step": "add 55555 TCP for all senders",
"traffic": {
"local": {
"ping": "ICMP 0/0 from 10.0.0.10",
"tcp": "connected",
"dns": "TimeOutException"
},
"remote": {
"ping": "ICMP 0/0 from 10.0.0.10",
"tcp": "connected",
"dns": "TimeOutException"
}
},
"active": {
"selected": true,
"enabled": true
},
"icmp": {
"selected": true,
"enabled": true
},
"udp": {
"selected": true,
"enabled": true
},
"port": "",
"protocol": "TCP",
"sender": "Alle Absender",
"rows": [
[
"TCP",
"55555",
"Alle Absender"
]
],
"log": "Portregel wurde hinzugefügt: 55555/TCP\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\n",
"logEditable": true
},
{
"step": "add 53 UDP for the same network",
"traffic": {
"local": {
"ping": "ICMP 0/0 from 10.0.0.10",
"tcp": "connected",
"dns": "10.0.0.10"
},
"remote": {
"ping": "ICMP 0/0 from 10.0.0.10",
"tcp": "connected",
"dns": "TimeOutException"
}
},
"active": {
"selected": true,
"enabled": true
},
"icmp": {
"selected": true,
"enabled": true
},
"udp": {
"selected": true,
"enabled": true
},
"port": "",
"protocol": "UDP",
"sender": "Absender im gleichen Rechnernetz",
"rows": [
[
"TCP",
"55555",
"Alle Absender"
],
[
"UDP",
"53",
"Nur lokales Rechnernetz"
]
],
"log": "Portregel wurde hinzugefügt: 55555/TCP\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nPortregel wurde hinzugefügt: 53/UDP\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #2 (10.0.0.0/255.255.255.0 -> */*; UDP:53 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\n",
"logEditable": true
},
{
"step": "ICMP no longer allowed",
"traffic": {
"local": {
"ping": "null",
"tcp": "connected",
"dns": "10.0.0.10"
},
"remote": {
"ping": "null",
"tcp": "connected",
"dns": "TimeOutException"
}
},
"active": {
"selected": true,
"enabled": true
},
"icmp": {
"selected": false,
"enabled": true
},
"udp": {
"selected": true,
"enabled": true
},
"port": "",
"protocol": "UDP",
"sender": "Absender im gleichen Rechnernetz",
"rows": [
[
"TCP",
"55555",
"Alle Absender"
],
[
"UDP",
"53",
"Nur lokales Rechnernetz"
]
],
"log": "Portregel wurde hinzugefügt: 55555/TCP\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nPortregel wurde hinzugefügt: 53/UDP\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #2 (10.0.0.0/255.255.255.0 -> */*; UDP:53 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 10.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #2 (10.0.0.0/255.255.255.0 -> */*; UDP:53 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 20.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\n",
"logEditable": true
},
{
"step": "UDP filter off",
"traffic": {
"local": {
"ping": "null",
"tcp": "connected",
"dns": "10.0.0.10"
},
"remote": {
"ping": "null",
"tcp": "connected",
"dns": "10.0.0.10"
}
},
"active": {
"selected": true,
"enabled": true
},
"icmp": {
"selected": false,
"enabled": true
},
"udp": {
"selected": false,
"enabled": true
},
"port": "",
"protocol": "UDP",
"sender": "Absender im gleichen Rechnernetz",
"rows": [
[
"TCP",
"55555",
"Alle Absender"
],
[
"UDP",
"53",
"Nur lokales Rechnernetz"
]
],
"log": "Portregel wurde hinzugefügt: 55555/TCP\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nPortregel wurde hinzugefügt: 53/UDP\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #2 (10.0.0.0/255.255.255.0 -> */*; UDP:53 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 10.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #2 (10.0.0.0/255.255.255.0 -> */*; UDP:53 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 20.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 10.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 20.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\n",
"logEditable": true
},
{
"step": "add -1 for all protocols",
"active": {
"selected": true,
"enabled": true
},
"icmp": {
"selected": false,
"enabled": true
},
"udp": {
"selected": false,
"enabled": true
},
"port": "",
"protocol": "*",
"sender": "Alle Absender",
"rows": [
[
"TCP",
"55555",
"Alle Absender"
],
[
"UDP",
"53",
"Nur lokales Rechnernetz"
],
[
"*",
"",
"Alle Absender"
]
],
"log": "Portregel wurde hinzugefügt: 55555/TCP\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nPortregel wurde hinzugefügt: 53/UDP\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #2 (10.0.0.0/255.255.255.0 -> */*; UDP:53 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 10.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #2 (10.0.0.0/255.255.255.0 -> */*; UDP:53 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 20.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 10.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 20.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nPortregel wurde hinzugefügt: -1/*\n",
"logEditable": true
},
{
"step": "add 0 TCP",
"active": {
"selected": true,
"enabled": true
},
"icmp": {
"selected": false,
"enabled": true
},
"udp": {
"selected": false,
"enabled": true
},
"port": "",
"protocol": "TCP",
"sender": "Alle Absender",
"rows": [
[
"TCP",
"55555",
"Alle Absender"
],
[
"UDP",
"53",
"Nur lokales Rechnernetz"
],
[
"*",
"",
"Alle Absender"
],
[
"TCP",
"0",
"Alle Absender"
]
],
"log": "Portregel wurde hinzugefügt: 55555/TCP\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nPortregel wurde hinzugefügt: 53/UDP\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #2 (10.0.0.0/255.255.255.0 -> */*; UDP:53 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 10.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #2 (10.0.0.0/255.255.255.0 -> */*; UDP:53 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 20.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 10.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 20.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nPortregel wurde hinzugefügt: -1/*\nPortregel wurde hinzugefügt: 0/TCP\n",
"logEditable": true
},
{
"step": "add 70000 TCP for the same network",
"active": {
"selected": true,
"enabled": true
},
"icmp": {
"selected": false,
"enabled": true
},
"udp": {
"selected": false,
"enabled": true
},
"port": "",
"protocol": "TCP",
"sender": "Absender im gleichen Rechnernetz",
"rows": [
[
"TCP",
"55555",
"Alle Absender"
],
[
"UDP",
"53",
"Nur lokales Rechnernetz"
],
[
"*",
"",
"Alle Absender"
],
[
"TCP",
"0",
"Alle Absender"
],
[
"TCP",
"70000",
"Nur lokales Rechnernetz"
]
],
"log": "Portregel wurde hinzugefügt: 55555/TCP\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nPortregel wurde hinzugefügt: 53/UDP\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #2 (10.0.0.0/255.255.255.0 -> */*; UDP:53 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 10.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #2 (10.0.0.0/255.255.255.0 -> */*; UDP:53 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 20.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 10.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 20.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nPortregel wurde hinzugefügt: -1/*\nPortregel wurde hinzugefügt: 0/TCP\nPortregel wurde hinzugefügt: 70000/TCP\n",
"logEditable": true
},
{
"step": "add a port after a space",
"active": {
"selected": true,
"enabled": true
},
"icmp": {
"selected": false,
"enabled": true
},
"udp": {
"selected": false,
"enabled": true
},
"port": " 80",
"protocol": "TCP",
"sender": "Alle Absender",
"rows": [
[
"TCP",
"55555",
"Alle Absender"
],
[
"UDP",
"53",
"Nur lokales Rechnernetz"
],
[
"*",
"",
"Alle Absender"
],
[
"TCP",
"0",
"Alle Absender"
],
[
"TCP",
"70000",
"Nur lokales Rechnernetz"
]
],
"log": "Portregel wurde hinzugefügt: 55555/TCP\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nPortregel wurde hinzugefügt: 53/UDP\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #2 (10.0.0.0/255.255.255.0 -> */*; UDP:53 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 10.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #2 (10.0.0.0/255.255.255.0 -> */*; UDP:53 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 20.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 10.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 20.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nPortregel wurde hinzugefügt: -1/*\nPortregel wurde hinzugefügt: 0/TCP\nPortregel wurde hinzugefügt: 70000/TCP\n",
"logEditable": true
},
{
"step": "delete with no row chosen",
"active": {
"selected": true,
"enabled": true
},
"icmp": {
"selected": false,
"enabled": true
},
"udp": {
"selected": false,
"enabled": true
},
"port": " 80",
"protocol": "TCP",
"sender": "Alle Absender",
"rows": [
[
"TCP",
"55555",
"Alle Absender"
],
[
"UDP",
"53",
"Nur lokales Rechnernetz"
],
[
"*",
"",
"Alle Absender"
],
[
"TCP",
"0",
"Alle Absender"
],
[
"TCP",
"70000",
"Nur lokales Rechnernetz"
]
],
"log": "Portregel wurde hinzugefügt: 55555/TCP\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nPortregel wurde hinzugefügt: 53/UDP\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #2 (10.0.0.0/255.255.255.0 -> */*; UDP:53 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 10.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #2 (10.0.0.0/255.255.255.0 -> */*; UDP:53 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 20.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 10.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 20.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nPortregel wurde hinzugefügt: -1/*\nPortregel wurde hinzugefügt: 0/TCP\nPortregel wurde hinzugefügt: 70000/TCP\n",
"logEditable": true
},
{
"step": "delete row 0",
"traffic": {
"local": {
"ping": "null",
"tcp": "connected",
"dns": "10.0.0.10"
},
"remote": {
"ping": "null",
"tcp": "connected",
"dns": "10.0.0.10"
}
},
"active": {
"selected": true,
"enabled": true
},
"icmp": {
"selected": false,
"enabled": true
},
"udp": {
"selected": false,
"enabled": true
},
"port": " 80",
"protocol": "TCP",
"sender": "Alle Absender",
"rows": [
[
"UDP",
"53",
"Nur lokales Rechnernetz"
],
[
"*",
"",
"Alle Absender"
],
[
"TCP",
"0",
"Alle Absender"
],
[
"TCP",
"70000",
"Nur lokales Rechnernetz"
]
],
"log": "Portregel wurde hinzugefügt: 55555/TCP\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nPortregel wurde hinzugefügt: 53/UDP\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #2 (10.0.0.0/255.255.255.0 -> */*; UDP:53 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 10.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #2 (10.0.0.0/255.255.255.0 -> */*; UDP:53 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 20.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 10.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 20.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nPortregel wurde hinzugefügt: -1/*\nPortregel wurde hinzugefügt: 0/TCP\nPortregel wurde hinzugefügt: 70000/TCP\nPortregel wurde entfernt.\nICMP-Paket verworfen: 10.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #2 (*/* -> */*; *:* => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 20.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #2 (*/* -> */*; *:* => ACCEPT) -> akzeptieren\n",
"logEditable": true
},
{
"step": "firewall off",
"traffic": {
"local": {
"ping": "ICMP 0/0 from 10.0.0.10",
"tcp": "connected",
"dns": "10.0.0.10"
},
"remote": {
"ping": "ICMP 0/0 from 10.0.0.10",
"tcp": "connected",
"dns": "10.0.0.10"
}
},
"active": {
"selected": false,
"enabled": true
},
"icmp": {
"selected": false,
"enabled": false
},
"udp": {
"selected": false,
"enabled": false
},
"port": " 80",
"protocol": "TCP",
"sender": "Alle Absender",
"rows": [
[
"UDP",
"53",
"Nur lokales Rechnernetz"
],
[
"*",
"",
"Alle Absender"
],
[
"TCP",
"0",
"Alle Absender"
],
[
"TCP",
"70000",
"Nur lokales Rechnernetz"
]
],
"log": "Portregel wurde hinzugefügt: 55555/TCP\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nPortregel wurde hinzugefügt: 53/UDP\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #2 (10.0.0.0/255.255.255.0 -> */*; UDP:53 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 10.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #2 (10.0.0.0/255.255.255.0 -> */*; UDP:53 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 20.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 10.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 20.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nPortregel wurde hinzugefügt: -1/*\nPortregel wurde hinzugefügt: 0/TCP\nPortregel wurde hinzugefügt: 70000/TCP\nPortregel wurde entfernt.\nICMP-Paket verworfen: 10.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #2 (*/* -> */*; *:* => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 20.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #2 (*/* -> */*; *:* => ACCEPT) -> akzeptieren\n",
"logEditable": true
},
{
"step": "firewall on again",
"active": {
"selected": true,
"enabled": true
},
"icmp": {
"selected": false,
"enabled": true
},
"udp": {
"selected": false,
"enabled": true
},
"port": " 80",
"protocol": "TCP",
"sender": "Alle Absender",
"rows": [
[
"UDP",
"53",
"Nur lokales Rechnernetz"
],
[
"*",
"",
"Alle Absender"
],
[
"TCP",
"0",
"Alle Absender"
],
[
"TCP",
"70000",
"Nur lokales Rechnernetz"
]
],
"log": "Portregel wurde hinzugefügt: 55555/TCP\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nPortregel wurde hinzugefügt: 53/UDP\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #2 (10.0.0.0/255.255.255.0 -> */*; UDP:53 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 10.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nFirewall-Regel hat gegriffen: #2 (10.0.0.0/255.255.255.0 -> */*; UDP:53 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 20.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 10.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 20.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:55555 => ACCEPT) -> akzeptieren\nPortregel wurde hinzugefügt: -1/*\nPortregel wurde hinzugefügt: 0/TCP\nPortregel wurde hinzugefügt: 70000/TCP\nPortregel wurde entfernt.\nICMP-Paket verworfen: 10.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #2 (*/* -> */*; *:* => ACCEPT) -> akzeptieren\nICMP-Paket verworfen: 20.0.0.2 -> 10.0.0.10 (code: 0, type: 8)\nFirewall-Regel hat gegriffen: #2 (*/* -> */*; *:* => ACCEPT) -> akzeptieren\n",
"logEditable": true
}
]
}
+238
View File
@@ -0,0 +1,238 @@
// A computer's firewall as Java's window changes it, against Java's
// (firewallWindow.java.json, FirewallWindowRun) on firewall-pc's server:
// Java's steps played on the engine — the boxes, the rules as the window's
// table shows them, the log, and after the steps that ask, what reaches the
// server from a computer of its network and one behind the router (a ping,
// a TCP connection to its echo server, its DNS server asked) — and where
// Java errs, what the firewall does instead (apps/personalFirewall.ts names
// each): only a port is taken.
import { readFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { describe, expect, it } from 'vitest';
import {
DIRECTLY_CONNECTED_SOURCE_MARKER,
firewallLogText,
firewallPortOfText,
firewallRule,
JAVA_PERSONAL_FIREWALL_DEFAULTS,
NetworkRuntimeEngine,
portRuleSender,
VirtualFileSystem,
withoutRule,
withPortRule,
withSnapshot,
type FirewallRule,
type PortRuleProtocol,
type Steps,
} from '../src/index.js';
import { snapshotOf, type Scenario } from './scenario.js';
interface Reached {
readonly ping: string;
readonly tcp: string;
readonly dns: string;
}
interface JavaStep {
readonly step: string;
readonly traffic?: { readonly local: Reached; readonly remote: Reached };
readonly active: { readonly selected: boolean; readonly enabled: boolean };
readonly icmp: { readonly selected: boolean; readonly enabled: boolean };
readonly udp: { readonly selected: boolean; readonly enabled: boolean };
readonly rows: readonly (readonly string[])[];
readonly log: string;
readonly logEditable: boolean;
}
const here = dirname(fileURLToPath(import.meta.url));
const java = JSON.parse(readFileSync(join(here, 'firewallWindow.java.json'), 'utf8')) as { readonly steps: readonly JavaStep[] };
const scenario = JSON.parse(readFileSync(join(here, 'scenarios/firewall-pc.scenario.json'), 'utf8')) as Scenario;
const LOCAL = '00000000-0000-0000-0000-000000000201';
const REMOTE = '00000000-0000-0000-0000-000000000203';
const SERVER = '00000000-0000-0000-0000-000000000204';
const SERVER_ADDRESS = '10.0.0.10';
const TIMED_OUT = 'TimeOutException: Zeitüberschreitung beim Verbindungsaufbau';
/** Java's ruleToVector: protocol, port, sender. */
function javaRow(rule: FirewallRule): string[] {
const protocol = rule.protocol === 'tcp' ? 'TCP' : rule.protocol === 'udp' ? 'UDP' : '*';
return [protocol, rule.port >= 0 ? String(rule.port) : '', rule.sourceIPAddress === DIRECTLY_CONNECTED_SOURCE_MARKER ? 'Nur lokales Rechnernetz' : 'Alle Absender'];
}
function setUp() {
const engine = new NetworkRuntimeEngine(scenario.seed);
engine.handle({
type: 'start',
snapshot: withSnapshot(snapshotOf(scenario), {
fileSystemsByNodeId: new Map([[SERVER, new VirtualFileSystem()]]),
echoServersByNodeId: new Map([[SERVER, { port: 55555, isActive: true }]]),
firewallConfigurationsByNodeId: new Map([[SERVER, JAVA_PERSONAL_FIREWALL_DEFAULTS]]),
}),
seed: scenario.seed,
initialTimeMilliseconds: 0,
});
const run = (milliseconds: number) => engine.handle({ type: 'advance', toMilliseconds: engine.state.currentTimeMilliseconds + milliseconds });
const blocking = <T>(steps: Steps<T>, milliseconds: number): T | undefined => {
let result: T | undefined;
engine.startThread(
(function* (): Steps {
result = yield* steps;
})(),
);
run(milliseconds);
return result;
};
let sequenceNumber = 1;
const reached = (from: string): Reached => {
const answer = blocking(engine.icmpEchoSteps(from, SERVER_ADDRESS, { identifier: 1, sequenceNumber: sequenceNumber++ }), 30_000);
const ping = answer?.message.kind === 'echoReply' ? `ICMP 0/0 from ${answer.packet.senderIPAddress}` : 'null';
const socket = engine.openTcpClientSocket(from, SERVER_ADDRESS, 55555)!;
const connected = blocking(engine.connectTcpSteps(socket), 60_000);
// Held a moment, as the oracle holds it.
run(500);
engine.closeSocket(socket);
run(1000);
const tcp = connected === 'connected' ? 'connected' : connected === 'timedOut' ? TIMED_OUT : String(connected);
const resolution = blocking(engine.resolveDnsAddressSteps(from, 'www.filius.de'), 30_000);
const dns = resolution === undefined || resolution.type === 'timedOut' ? 'TimeOutException' : String(resolution.address ?? null);
return { ping, tcp, dns };
};
return { engine, reached };
}
describe("a computer's firewall window, against Java's", () => {
it("plays Java's steps: the same where Java is right, as named where it errs", () => {
const { engine, reached } = setUp();
const configuration = () => engine.personalFirewall(SERVER)!;
const log = () => engine.firewallLog(SERVER).map((entry) => `${firewallLogText(entry, 'de')}\n`);
// Java's log lines, less those of what Java takes and the firewall does not (and with those the firewall takes instead).
let javaLines = (step: JavaStep) => step.log.split(/(?<=\n)/).filter((line) => line !== '');
const at = (name: string) => java.steps.find((step) => step.step === name)!;
const check = (name: string, traffic: { readonly local: Reached; readonly remote: Reached } | undefined = at(name).traffic) => {
const step = at(name);
if (traffic !== undefined) expect({ local: reached(LOCAL), remote: reached(REMOTE) }, name).toEqual(traffic);
expect({ active: configuration().isActive, icmp: !configuration().dropIcmp, udp: configuration().filterUdp, rows: configuration().rules.map(javaRow), log: log() }, name).toEqual({
active: step.active.selected,
icmp: step.icmp.selected,
udp: step.udp.selected,
rows: step.rows,
log: javaLines(step),
});
};
const add = (port: string, protocol: PortRuleProtocol, sameNetworkOnly: boolean) => {
const number = firewallPortOfText(port);
return number !== undefined && engine.addFirewallPortRule(SERVER, number, protocol, sameNetworkOnly);
};
const set = (fields: Partial<ReturnType<typeof configuration>>) => engine.setFirewallConfiguration(SERVER, { ...configuration(), ...fields });
// Active as Java installs it: a ping goes through, TCP and UDP only by a rule.
check('open');
expect(at('open').logEditable).toBe(true);
expect([add('abc', 'tcp', false), add('', 'tcp', false)]).toEqual([false, false]);
check('add port abc');
check('add an empty port');
expect(add('55555', 'tcp', false)).toBe(true);
check('add 55555 TCP for all senders');
expect(add('53', 'udp', true)).toBe(true);
check('add 53 UDP for the same network');
set({ dropIcmp: true });
check('ICMP no longer allowed');
set({ filterUdp: false });
check('UDP filter off');
// No port, none taken (Java takes each: -1 a rule for every port of both protocols, 0 and 70000 rules that never match).
expect([add('-1', 'all', false), add('0', 'tcp', false), add('70000', 'tcp', true)]).toEqual([false, false, false]);
const notTaken = ['Portregel wurde hinzugefügt: -1/*\n', 'Portregel wurde hinzugefügt: 0/TCP\n', 'Portregel wurde hinzugefügt: 70000/TCP\n'];
let javaRows = (step: JavaStep) => step.rows.filter(([, port]) => port !== '' && port !== '0' && port !== '70000');
const javaAll = javaLines;
javaLines = (step) => javaAll(step).filter((line) => !notTaken.includes(line));
const sameAsJava = (name: string) => expect({ rows: configuration().rules.map(javaRow), log: log() }, name).toEqual({ rows: javaRows(at(name)), log: javaLines(at(name)) });
for (const name of ['add -1 for all protocols', 'add 0 TCP', 'add 70000 TCP for the same network']) sameAsJava(name);
// A port after a space is taken (Java refuses it without a word).
expect(add(' 80', 'tcp', false)).toBe(true);
const tookPort = javaLines(at('add 70000 TCP for the same network')).length;
const javaTaken = javaLines;
javaLines = (step) => javaTaken(step).toSpliced(tookPort, 0, 'Portregel wurde hinzugefügt: 80/TCP\n');
const javaListed = javaRows;
javaRows = (step) => [...javaListed(step), ['TCP', '80', 'Alle Absender']];
sameAsJava('add a port after a space');
// "Löschen" with no row chosen does nothing; row 0 goes. Without Java's rule for every port, TCP is no longer let through.
sameAsJava('delete with no row chosen');
expect(engine.removeFirewallRule(SERVER, 0)).toBe(true);
const javaKept = javaLines;
javaLines = (step) => javaKept(step).filter((line) => !line.includes('*/* -> */*; *:*'));
const javaDelete = at('delete row 0');
const closed = (reach: Reached): Reached => ({ ...reach, tcp: TIMED_OUT });
expect({ local: reached(LOCAL), remote: reached(REMOTE) }).toEqual({ local: closed(javaDelete.traffic!.local), remote: closed(javaDelete.traffic!.remote) });
sameAsJava('delete row 0');
// Off: everything goes through, nothing is written; on again.
set({ isActive: false });
const javaOff = at('firewall off');
expect({ local: reached(LOCAL), remote: reached(REMOTE) }).toEqual(javaOff.traffic);
sameAsJava('firewall off');
expect([javaOff.icmp.enabled, javaOff.udp.enabled, at('firewall on again').icmp.enabled]).toEqual([false, false, true]);
set({ isActive: true });
expect(configuration()).toMatchObject({ isActive: true, dropIcmp: true, filterUdp: false });
});
});
describe("a computer's firewall beyond the steps", () => {
it('takes a port of 1 to 65535 only, spaces around it allowed', () => {
expect(['1', '65535', ' 80 ', '+80', '80a', '0', '65536', '-1', '', ' '].map(firewallPortOfText)).toEqual([
1,
65535,
80,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
]);
});
it('adds Java’s rule and removes the row chosen only', () => {
const added = withPortRule(withPortRule(JAVA_PERSONAL_FIREWALL_DEFAULTS, 80, 'tcp', false), 53, 'udp', true);
expect(added.rules).toEqual([
firewallRule({ port: 80, protocol: 'tcp', action: 'accept' }),
firewallRule({ port: 53, protocol: 'udp', action: 'accept', sourceIPAddress: DIRECTLY_CONNECTED_SOURCE_MARKER }),
]);
expect(withoutRule(added, 1)!.rules).toEqual([added.rules[0]]);
expect([withoutRule(added, 2), withoutRule(added, -1), withoutRule(added, 0.5)]).toEqual([undefined, undefined, undefined]);
});
it("names the window's sender for the rules it makes only", () => {
expect(
[
firewallRule({ action: 'accept' }),
firewallRule({ action: 'accept', sourceIPAddress: DIRECTLY_CONNECTED_SOURCE_MARKER, sourceSubnetMask: '255.0.0.0' }),
firewallRule({ action: 'accept', sourceSubnetMask: '255.0.0.0' }),
firewallRule({ action: 'drop' }),
firewallRule({ action: 'accept', sourceIPAddress: '10.0.0.0', sourceSubnetMask: '255.0.0.0' }),
firewallRule({ action: 'accept', destinationIPAddress: '10.0.0.10' }),
].map(portRuleSender),
).toEqual(['all', 'sameNetwork', 'all', undefined, undefined, undefined]);
});
it('has nothing for a computer without a firewall, nor a router', () => {
const engine = new NetworkRuntimeEngine(scenario.seed);
// The router has a firewall, as every one has in Java; it is no program of a computer.
const ROUTER = '00000000-0000-0000-0000-000000000202';
engine.handle({
type: 'start',
snapshot: withSnapshot(snapshotOf(scenario), { firewallConfigurationsByNodeId: new Map([[ROUTER, JAVA_PERSONAL_FIREWALL_DEFAULTS]]) }),
seed: scenario.seed,
initialTimeMilliseconds: 0,
});
expect([engine.personalFirewall(SERVER), engine.personalFirewall(ROUTER)]).toEqual([undefined, undefined]);
expect(engine.addFirewallPortRule(ROUTER, 80, 'tcp', false)).toBe(false);
expect([engine.addFirewallPortRule(SERVER, 80, 'tcp', false), engine.removeFirewallRule(SERVER, 0)]).toEqual([false, false]);
expect(engine.firewallLog(SERVER)).toEqual([]);
});
});
@@ -0,0 +1,146 @@
{
"seed": 21,
"nodes": [
{
"id": "00000000-0000-0000-0000-000000000201",
"kind": "pc",
"ports": [
{
"id": "00000000-0000-0000-0000-000000000211",
"label": "eth0"
}
]
},
{
"id": "00000000-0000-0000-0000-000000000202",
"kind": "router",
"ports": [
{
"id": "00000000-0000-0000-0000-000000000221",
"label": "rt1"
},
{
"id": "00000000-0000-0000-0000-000000000222",
"label": "rt2"
}
]
},
{
"id": "00000000-0000-0000-0000-000000000203",
"kind": "pc",
"ports": [
{
"id": "00000000-0000-0000-0000-000000000213",
"label": "eth0"
}
]
},
{
"id": "00000000-0000-0000-0000-000000000204",
"kind": "pc",
"ports": [
{
"id": "00000000-0000-0000-0000-000000000214",
"label": "eth0"
}
]
},
{
"id": "00000000-0000-0000-0000-000000000205",
"kind": "networkSwitch",
"ports": [
{
"id": "00000000-0000-0000-0000-000000000251",
"label": "sw1"
},
{
"id": "00000000-0000-0000-0000-000000000252",
"label": "sw2"
},
{
"id": "00000000-0000-0000-0000-000000000253",
"label": "sw3"
},
{
"id": "00000000-0000-0000-0000-000000000254",
"label": "sw4"
}
]
}
],
"links": [
{
"id": "00000000-0000-0000-0000-00000000F301",
"sourceNode": "00000000-0000-0000-0000-000000000201",
"sourcePort": "00000000-0000-0000-0000-000000000211",
"targetNode": "00000000-0000-0000-0000-000000000205",
"targetPort": "00000000-0000-0000-0000-000000000251"
},
{
"id": "00000000-0000-0000-0000-00000000F302",
"sourceNode": "00000000-0000-0000-0000-000000000204",
"sourcePort": "00000000-0000-0000-0000-000000000214",
"targetNode": "00000000-0000-0000-0000-000000000205",
"targetPort": "00000000-0000-0000-0000-000000000252"
},
{
"id": "00000000-0000-0000-0000-00000000F303",
"sourceNode": "00000000-0000-0000-0000-000000000202",
"sourcePort": "00000000-0000-0000-0000-000000000221",
"targetNode": "00000000-0000-0000-0000-000000000205",
"targetPort": "00000000-0000-0000-0000-000000000253"
},
{
"id": "00000000-0000-0000-0000-00000000F304",
"sourceNode": "00000000-0000-0000-0000-000000000202",
"sourcePort": "00000000-0000-0000-0000-000000000222",
"targetNode": "00000000-0000-0000-0000-000000000203",
"targetPort": "00000000-0000-0000-0000-000000000213"
}
],
"devices": {
"00000000-0000-0000-0000-000000000201": {
"ip": "10.0.0.2",
"mask": "255.255.255.0",
"gateway": "10.0.0.1",
"dns": "10.0.0.10"
},
"00000000-0000-0000-0000-000000000202": {
"ip": "10.0.0.1",
"mask": "255.255.255.0"
},
"00000000-0000-0000-0000-000000000203": {
"ip": "20.0.0.2",
"mask": "255.255.255.0",
"gateway": "20.0.0.1",
"dns": "10.0.0.10"
},
"00000000-0000-0000-0000-000000000204": {
"ip": "10.0.0.10",
"mask": "255.255.255.0",
"gateway": "10.0.0.1"
}
},
"interfaces": [
{
"node": "00000000-0000-0000-0000-000000000202",
"port": "00000000-0000-0000-0000-000000000221",
"ip": "10.0.0.1",
"mask": "255.255.255.0"
},
{
"node": "00000000-0000-0000-0000-000000000202",
"port": "00000000-0000-0000-0000-000000000222",
"ip": "20.0.0.1",
"mask": "255.255.255.0"
}
],
"dnsServers": {
"00000000-0000-0000-0000-000000000204": {
"records": [
"www.filius.de A 10.0.0.10"
]
}
}
,"steps": []
}