From db087a251e3014733d73816bfda9e91d43e5992a Mon Sep 17 00:00:00 2001
From: tetuaoro <65575727+tetuaoro@users.noreply.github.com>
Date: Tue, 23 Jul 2024 20:10:07 +0200
Subject: [PATCH] feat: firewall
- add rule on chain WGEASY
- delete rule on chain WGEASY
- restore if rules config exists otherwise create new config
---
src/lib/Firewall.js | 22 ++++
src/lib/Server.js | 16 +++
src/lib/Util.js | 32 +++++
src/server.js | 13 +-
src/tailwind.config.js | 2 +-
src/www/css/app.css | 5 +
src/www/js/api.js | 27 +++++
src/www/js/i18n.js | 19 ++-
src/www/js/vendor/vue-firewall.umd.min.js | 2 +-
src/www/js/vendor/vue-firewall.umd.min.js.map | 2 +-
src/www/templates/Firewall.vue | 111 +++++++++++++-----
11 files changed, 217 insertions(+), 34 deletions(-)
diff --git a/src/lib/Firewall.js b/src/lib/Firewall.js
index b7a6c0a6..bd873524 100644
--- a/src/lib/Firewall.js
+++ b/src/lib/Firewall.js
@@ -46,6 +46,7 @@ module.exports = class Firewall {
async getIptablesRules() {
// iptables list the rules WG_IPT_CHAIN_NAME chain
+<<<<<<< HEAD
//
// $ iptables -L WGEASY -nv --line-numbers
// Chain WGEASY (0 references)
@@ -56,6 +57,18 @@ module.exports = class Firewall {
// Chain (0 references)
// num target prot source destination
// 1 ACCEPT 6 172.16.7.2 10.8.2.5
+=======
+ // $ iptables -L ${WG_IPT_CHAIN_NAME} -n -v
+ // Chain WGEASY (0 references)
+ // num pkts bytes target prot opt in out source destination
+ // 1 0 0 DROP 6 -- * * 172.16.8.2 172.16.8.3
+ // 2 0 0 ACCEPT 6 -- * * 172.16.9.2 172.16.8.3
+ // $ iptables -L ${WG_IPT_CHAIN_NAME} -n -v | awk '{print $3,$4,$8,$9}'
+ // (0 references)
+ // num target prot source destination
+ // 1 DROP 6 172.16.8.2 172.16.8.3
+ // 2 ACCEPT 6 172.16.9.2 172.16.8.3
+>>>>>>> 9ec7359 (feat: firewall)
const stdout = await Util.exec(`iptables -L ${WG_IPT_CHAIN_NAME} -nv --line-numbers | awk '{print $1,$4,$5,$9,$10}'`);
const lines = stdout.split(/\r?\n/);
@@ -74,6 +87,7 @@ module.exports = class Firewall {
async addIptablesRule(source, destination, protocol, target) {
debug('Rule adding...');
+<<<<<<< HEAD
// Validate target & protocol
if (!Util.isTarget(target) || !Util.isProtocol(protocol)) {
throw new Error('Invalid target or protocol.');
@@ -117,6 +131,14 @@ module.exports = class Firewall {
iptablesCommand += ` -p ${protocol} -j ${target}`;
await Util.exec(iptablesCommand);
+=======
+ // Validate target
+ if (target !== 'ACCEPT' && target !== 'DROP') {
+ throw new Error('Invalid action. Must be "ACCEPT" or "DROP".');
+ }
+
+ await Util.exec(`iptables -A ${WG_IPT_CHAIN_NAME} -s ${source} -d ${destination} -p ${protocol} -j ${target}`);
+>>>>>>> 9ec7359 (feat: firewall)
await this.__saveIptablesRules();
debug('Rule added');
}
diff --git a/src/lib/Server.js b/src/lib/Server.js
index 2031484e..3998b747 100644
--- a/src/lib/Server.js
+++ b/src/lib/Server.js
@@ -284,6 +284,22 @@ module.exports = class Server {
.get('/api/fw/interfaces', defineEventHandler(async (event) => {
setHeader(event, 'Content-Type', 'text/json');
return Firewall.getInterfaces();
+ }))
+ .get('/api/fw/rules', defineEventHandler(async (event) => {
+ setHeader(event, 'Content-Type', 'text/json');
+ return Firewall.getIptablesRules();
+ }))
+ .post('/api/fw/rule', defineEventHandler(async (event) => {
+ const {
+ source, destination, protocol, target,
+ } = await readBody(event);
+ await Firewall.addIptablesRule(source, destination, protocol, target);
+ return { success: true };
+ }))
+ .delete('/api/fw/rule', defineEventHandler(async (event) => {
+ const { num } = await readBody(event);
+ await Firewall.deleteIptablesRule(num);
+ return { success: true };
}));
// Static assets
diff --git a/src/lib/Util.js b/src/lib/Util.js
index cc6e89c2..aa311796 100644
--- a/src/lib/Util.js
+++ b/src/lib/Util.js
@@ -2,6 +2,30 @@
const childProcess = require('child_process');
+const Protocol = Object.freeze({
+ ALL: 0,
+ TCP: 6,
+ UDP: 17,
+});
+
+const ProtocolName = Object.freeze({
+ [Protocol.ALL]: '*',
+ [Protocol.TCP]: 'TCP',
+ [Protocol.UDP]: 'UDP',
+});
+
+const Target = Object.freeze({
+ RETURN: 'RETURN',
+ ALLOW: 'ACCEPT',
+ BLOCK: 'DROP',
+});
+
+const TargetName = Object.freeze({
+ [Target.RETURN]: 'RETURN',
+ [Target.ALLOW]: 'ALLOW',
+ [Target.BLOCK]: 'BLOCK',
+});
+
module.exports = class Util {
static isValidIPv4(str) {
@@ -77,4 +101,12 @@ module.exports = class Util {
});
}
+ static getProtocolName(protocolNumber) {
+ return ProtocolName[protocolNumber] || 'Unknown Protocol';
+ }
+
+ static getTargetName(target) {
+ return TargetName[target] || 'Unknown Target';
+ }
+
};
diff --git a/src/server.js b/src/server.js
index 66887101..65d34055 100644
--- a/src/server.js
+++ b/src/server.js
@@ -1,13 +1,22 @@
'use strict';
require('./services/Server');
-require('./services/Firewall');
const WireGuard = require('./services/WireGuard');
+const Firewall = require('./services/Firewall');
WireGuard.getConfig()
+ .then(() => {
+ Firewall.init().catch((err) => {
+ // eslint-disable-next-line no-console
+ console.error(err);
+
+ // eslint-disable-next-line no-process-exit
+ process.exit(1);
+ });
+ })
.catch((err) => {
- // eslint-disable-next-line no-console
+ // eslint-disable-next-line no-console
console.error(err);
// eslint-disable-next-line no-process-exit
diff --git a/src/tailwind.config.js b/src/tailwind.config.js
index bc7b40da..8f1fb66c 100644
--- a/src/tailwind.config.js
+++ b/src/tailwind.config.js
@@ -4,7 +4,7 @@
module.exports = {
darkMode: 'selector',
- content: ['./www/**/*.{html,js}'],
+ content: ['./www/**/*.{html,js,vue}'],
theme: {
screens: {
xxs: '450px',
diff --git a/src/www/css/app.css b/src/www/css/app.css
index 98d7df7b..7c1c4064 100644
--- a/src/www/css/app.css
+++ b/src/www/css/app.css
@@ -1515,6 +1515,11 @@ video {
background-color: rgb(249 250 251 / var(--tw-bg-opacity));
}
+.hover\:bg-green-600:hover {
+ --tw-bg-opacity: 1;
+ background-color: rgb(22 163 74 / var(--tw-bg-opacity));
+}
+
.hover\:bg-red-700:hover {
--tw-bg-opacity: 1;
background-color: rgb(185 28 28 / var(--tw-bg-opacity));
diff --git a/src/www/js/api.js b/src/www/js/api.js
index 728b66c4..f62b68eb 100644
--- a/src/www/js/api.js
+++ b/src/www/js/api.js
@@ -153,4 +153,31 @@ class API {
});
}
+ async getRules() {
+ return this.call({
+ method: 'get',
+ path: '/fw/rules',
+ });
+ }
+
+ async addRule({
+ source, destination, protocol, target,
+ }) {
+ return this.call({
+ method: 'post',
+ path: '/fw/rule',
+ body: {
+ source, destination, protocol, target,
+ },
+ });
+ }
+
+ async deleteRule({ num }) {
+ return this.call({
+ method: 'delete',
+ path: '/fw/rule',
+ body: { num },
+ });
+ }
+
}
diff --git a/src/www/js/i18n.js b/src/www/js/i18n.js
index d66f5fd8..7511438c 100644
--- a/src/www/js/i18n.js
+++ b/src/www/js/i18n.js
@@ -34,7 +34,15 @@ const messages = { // eslint-disable-line no-unused-vars
backup: 'Backup',
titleRestoreConfig: 'Restore your configuration',
titleBackupConfig: 'Backup your configuration',
- firewall: 'Firewall',
+ fwFirewall: 'Firewall',
+ fwInterface: 'Interface',
+ fwIpv4: 'IPv4 address',
+ fwIpv6: 'IPv6 address',
+ fwAction: 'Action',
+ fwSource: 'Source',
+ fwDestination: 'Destination',
+ fwProtocol: 'Protocol',
+ fwTarget: 'Target',
},
ua: {
name: 'Ім`я',
@@ -209,6 +217,15 @@ const messages = { // eslint-disable-line no-unused-vars
backup: 'Sauvegarder',
titleRestoreConfig: 'Restaurer votre configuration',
titleBackupConfig: 'Sauvegarder votre configuration',
+ fwFirewall: 'Parefeu',
+ fwInterface: 'Interface',
+ fwIpv4: 'Address IPv4',
+ fwIpv6: 'Address IPv4',
+ fwAction: 'Action',
+ fwSource: 'Source',
+ fwDestination: 'Destination',
+ fwProtocol: 'Protocole',
+ fwTarget: 'Règle',
},
de: { // github.com/florian-asche
name: 'Name',
diff --git a/src/www/js/vendor/vue-firewall.umd.min.js b/src/www/js/vendor/vue-firewall.umd.min.js
index c5c79d30..8fa4326a 100644
--- a/src/www/js/vendor/vue-firewall.umd.min.js
+++ b/src/www/js/vendor/vue-firewall.umd.min.js
@@ -1,2 +1,2 @@
-(function(t,e){"object"===typeof exports&&"object"===typeof module?module.exports=e():"function"===typeof define&&define.amd?define([],e):"object"===typeof exports?exports["VueFirewall"]=e():t["VueFirewall"]=e()})("undefined"!==typeof self?self:this,(()=>(()=>{"use strict";var t={};(()=>{t.d=(e,r)=>{for(var a in r)t.o(r,a)&&!t.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:r[a]})}})(),(()=>{t.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e)})(),(()=>{t.p=""})();var e={};if(t.d(e,{default:()=>u}),"undefined"!==typeof window){var r=window.document.currentScript,a=r&&r.src.match(/(.+\/)[^/]+\.js(\?.*)?$/);a&&(t.p=a[1])}var s=function(){var t=this,e=t.$createElement,r=t._self._c||e;return r("div",{staticClass:"shadow-md rounded-lg bg-white dark:bg-neutral-700 overflow-hidden"},[r("div",{staticClass:"flex flex-row flex-auto items-center mb-4 p-3 px-5 border-b-2 border-gray-100 dark:border-neutral-600"},[r("div",{staticClass:"flex-grow"},[r("p",{staticClass:"text-2xl font-medium dark:text-neutral-200"},[t._v(t._s(t.$t("firewall")))])])]),r("table",{staticClass:"table-auto w-[70%] dark:text-neutral-200 mb-4"},[t._m(0),r("tbody",{staticClass:"text-center"},t._l(t.interfaces,(function(e,a){return r("tr",{key:a},[r("td",[t._v(t._s(e.name))]),r("td",[t._v(t._s(e.ipv4))]),r("td",[t._v(t._s(e.ipv6))])])})),0)]),t._m(1)])},o=[function(){var t=this,e=t.$createElement,r=t._self._c||e;return r("thead",[r("tr",[r("th",[t._v("Interface")]),r("th",[t._v("IPv4 address")]),r("th",[t._v("IPv6 address")])])])},function(){var t=this,e=t.$createElement,r=t._self._c||e;return r("table",{staticClass:"table-auto border-t-2 dark:border-neutral-200 w-full dark:text-neutral-200"},[r("thead",{staticClass:"bg-gray-200 dark:bg-gray-600"},[r("tr",[r("th",[t._v("Action")]),r("th",{staticClass:"border-x-2 dark:border-neutral-200"},[t._v("Source")]),r("th",{staticClass:"border-x-2 dark:border-neutral-200"},[t._v("Destination")]),r("th",{staticClass:"border-x-2 dark:border-neutral-200"},[t._v("Protocol")]),r("th")])]),r("tbody",{staticClass:"text-center"},[r("tr",[r("td",{staticClass:"border border-gray-600 p-1"},[t._v("delete")]),r("td",{staticClass:"border border-gray-600 p-1"},[t._v("192.168.11.3")]),r("td",{staticClass:"border border-gray-600 p-1"},[t._v("10.9.8.1")]),r("td",{staticClass:"border border-gray-600 p-1"},[t._v("udp")]),r("td",{staticClass:"border border-gray-600 p-1"})]),r("tr",[r("td",{staticClass:"border border-gray-600 p-1"},[r("form",{attrs:{id:"fw"}},[r("input",{staticClass:"w-full outline-none bg-transparent text-center",attrs:{form:"fw",type:"submit",value:"send"}})])]),r("td",{staticClass:"border border-gray-600"},[r("input",{staticClass:"w-full outline-none bg-transparent text-center",attrs:{form:"fw",type:"text",name:"source"}})]),r("td",{staticClass:"border border-gray-600"},[r("input",{staticClass:"w-full outline-none bg-transparent text-center",attrs:{form:"fw",type:"text",name:"destination"}})]),r("td",{staticClass:"border border-gray-600"},[r("select",{staticClass:"bg-transparent",attrs:{form:"fw",name:"protocol"}},[r("option",{attrs:{value:"tcp"}},[t._v("tcp")]),r("option",{attrs:{value:"udp"}},[t._v("udp")])])]),r("td",{staticClass:"border border-gray-600 p-1"},[r("select",{staticClass:"bg-transparent",attrs:{form:"fw",name:"action"}},[r("option",{attrs:{value:"allow"}},[t._v("allow")]),r("option",{attrs:{value:"block"}},[t._v("block")])])])])])])}];const n={name:"Firewall",data(){let t=[];return{interfaces:t}},methods:{getInterfaces(){this.api.getInterfaces().then((t=>{this.interfaces=t})).catch((t=>{alert(t.message||t.toString())}))}},mounted(){this.api=new API,this.getInterfaces()}},i=n;function d(t,e,r,a,s,o,n,i){var d,l="function"===typeof t?t.options:t;if(e&&(l.render=e,l.staticRenderFns=r,l._compiled=!0),a&&(l.functional=!0),o&&(l._scopeId="data-v-"+o),n?(d=function(t){t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext,t||"undefined"===typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),s&&s.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(n)},l._ssrRegister=d):s&&(d=i?function(){s.call(this,(l.functional?this.parent:this).$root.$options.shadowRoot)}:s),d)if(l.functional){l._injectStyles=d;var c=l.render;l.render=function(t,e){return d.call(e),c(t,e)}}else{var u=l.beforeCreate;l.beforeCreate=u?[].concat(u,d):[d]}return{exports:t,options:l}}var l=d(i,s,o,!1,null,null,null);const c=l.exports,u=c;return e=e["default"],e})()));
+(function(t,e){"object"===typeof exports&&"object"===typeof module?module.exports=e():"function"===typeof define&&define.amd?define([],e):"object"===typeof exports?exports["VueFirewall"]=e():t["VueFirewall"]=e()})("undefined"!==typeof self?self:this,(()=>(()=>{"use strict";var t={};(()=>{t.d=(e,r)=>{for(var a in r)t.o(r,a)&&!t.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:r[a]})}})(),(()=>{t.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e)})(),(()=>{t.p=""})();var e={};if(t.d(e,{default:()=>c}),"undefined"!==typeof window){var r=window.document.currentScript,a=r&&r.src.match(/(.+\/)[^/]+\.js(\?.*)?$/);a&&(t.p=a[1])}var s=function(){var t=this,e=t.$createElement,r=t._self._c||e;return r("div",{staticClass:"shadow-md rounded-lg bg-white dark:bg-neutral-700 overflow-hidden"},[r("div",{staticClass:"flex flex-row flex-auto items-center mb-4 p-3 px-5 border-b-2 border-gray-100 dark:border-neutral-600"},[r("div",{staticClass:"flex-grow"},[r("p",{staticClass:"text-2xl font-medium dark:text-neutral-200"},[t._v(t._s(t.$t("fwFirewall")))])])]),r("table",{staticClass:"table-auto w-[70%] dark:text-neutral-200 mb-4"},[r("thead",[r("tr",[r("th",[t._v(t._s(t.$t("fwInterface")))]),r("th",[t._v(t._s(t.$t("fwIv4")))]),r("th",[t._v(t._s(t.$t("fwIv6")))])])]),r("tbody",{staticClass:"text-center"},t._l(t.interfaces,(function(e,a){return r("tr",{key:a},[r("td",[t._v(t._s(e.name))]),r("td",[t._v(t._s(e.ipv4))]),r("td",[t._v(t._s(e.ipv6))])])})),0)]),r("table",{staticClass:"table-auto border-t-2 dark:border-neutral-200 w-full dark:text-neutral-200"},[r("thead",{staticClass:"bg-gray-200 dark:bg-gray-600"},[r("tr",[r("th",[t._v(t._s(t.$t("fwAction")))]),r("th",{staticClass:"border-x-2 dark:border-neutral-200"},[t._v(t._s(t.$t("fwSource")))]),r("th",{staticClass:"border-x-2 dark:border-neutral-200"},[t._v(t._s(t.$t("fwDestination")))]),r("th",{staticClass:"border-x-2 dark:border-neutral-200"},[t._v(t._s(t.$t("fwProtocol")))]),r("th",[t._v(t._s(t.$t("fwTarget")))])])]),r("tbody",{staticClass:"text-center"},[t._l(t.rules,(function(e,a){return r("tr",{key:a},[r("td",{staticClass:"border border-gray-600 p-1 hover:bg-red-800 transition"},[r("button",{on:{click:function(r){return t.deleteRule(e.num)}}},[r("svg",{staticClass:"size-6",attrs:{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor"}},[r("path",{attrs:{"stroke-linecap":"round","stroke-linejoin":"round",d:"M6 18 18 6M6 6l12 12"}})])])]),r("td",{staticClass:"border border-gray-600 p-1"},[t._v(t._s(e.source))]),r("td",{staticClass:"border border-gray-600 p-1"},[t._v(t._s(e.destination))]),r("td",{staticClass:"border border-gray-600 p-1"},[t._v(t._s(e.protocol))]),r("td",{staticClass:"border border-gray-600 p-1"},[t._v(t._s(e.target))])])})),r("tr",[r("td",{staticClass:"border border-gray-600 p-1 hover:bg-green-600 transition"},[r("form",{attrs:{id:"fw"},on:{submit:t.addRule}},[r("button",{attrs:{type:"submit"}},[r("svg",{staticClass:"size-6",attrs:{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor"}},[r("path",{attrs:{"stroke-linecap":"round","stroke-linejoin":"round",d:"M12 9v6m3-3H9m12 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"}})])])])]),r("td",{staticClass:"border border-gray-600"},[r("input",{directives:[{name:"model",rawName:"v-model",value:t.newRule.source,expression:"newRule.source"}],staticClass:"w-full outline-none bg-transparent text-center",attrs:{form:"fw",type:"text",name:"source"},domProps:{value:t.newRule.source},on:{input:function(e){e.target.composing||t.$set(t.newRule,"source",e.target.value)}}})]),r("td",{staticClass:"border border-gray-600"},[r("input",{directives:[{name:"model",rawName:"v-model",value:t.newRule.destination,expression:"newRule.destination"}],staticClass:"w-full outline-none bg-transparent text-center",attrs:{form:"fw",type:"text",name:"destination"},domProps:{value:t.newRule.destination},on:{input:function(e){e.target.composing||t.$set(t.newRule,"destination",e.target.value)}}})]),r("td",{staticClass:"border border-gray-600"},[r("select",{directives:[{name:"model",rawName:"v-model",value:t.newRule.protocol,expression:"newRule.protocol"}],staticClass:"bg-transparent",attrs:{form:"fw",name:"protocol"},on:{change:function(e){var r=Array.prototype.filter.call(e.target.options,(function(t){return t.selected})).map((function(t){var e="_value"in t?t._value:t.value;return e}));t.$set(t.newRule,"protocol",e.target.multiple?r:r[0])}}},[r("option",{attrs:{value:"tcp"}},[t._v("TCP")]),r("option",{attrs:{value:"udp"}},[t._v("UDP")])])]),r("td",{staticClass:"border border-gray-600 p-1"},[r("select",{directives:[{name:"model",rawName:"v-model",value:t.newRule.target,expression:"newRule.target"}],staticClass:"bg-transparent",attrs:{form:"fw",name:"target"},on:{change:function(e){var r=Array.prototype.filter.call(e.target.options,(function(t){return t.selected})).map((function(t){var e="_value"in t?t._value:t.value;return e}));t.$set(t.newRule,"target",e.target.multiple?r:r[0])}}},[r("option",{attrs:{value:"ACCEPT"}},[t._v("ALLOW")]),r("option",{attrs:{value:"DROP"}},[t._v("BLOCK")])])])])],2)])])},o=[];const n={name:"Firewall",data(){let t=[],e=[],r={source:"",destination:"",protocol:"",target:""};return{interfaces:t,rules:e,newRule:r}},methods:{getInterfaces(){this.api.getInterfaces().then((t=>{this.interfaces=t})).catch((t=>{alert(t.message||t.toString())}))},getRules(){this.api.getRules().then((t=>{this.rules=t})).catch((t=>{alert(t.message||t.toString())}))},addRule(t){t.preventDefault();const{source:e,destination:r,protocol:a,target:s}=this.newRule;this.api.addRule({source:e,destination:r,protocol:a,target:s}).then((()=>{this.getRules()})).then((()=>{this.newRule={source:"",destination:"",protocol:"",target:""}})).catch((t=>{alert(t.message||t.toString())}))},deleteRule(t){this.api.deleteRule({num:t}).then((()=>{this.getRules()})).catch((t=>{alert(t.message||t.toString())}))}},mounted(){this.api=new API,this.getInterfaces(),this.getRules()}},i=n;function l(t,e,r,a,s,o,n,i){var l,d="function"===typeof t?t.options:t;if(e&&(d.render=e,d.staticRenderFns=r,d._compiled=!0),a&&(d.functional=!0),o&&(d._scopeId="data-v-"+o),n?(l=function(t){t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext,t||"undefined"===typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),s&&s.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(n)},d._ssrRegister=l):s&&(l=i?function(){s.call(this,(d.functional?this.parent:this).$root.$options.shadowRoot)}:s),l)if(d.functional){d._injectStyles=l;var u=d.render;d.render=function(t,e){return l.call(e),u(t,e)}}else{var c=d.beforeCreate;d.beforeCreate=c?[].concat(c,l):[l]}return{exports:t,options:d}}var d=l(i,s,o,!1,null,null,null);const u=d.exports,c=u;return e=e["default"],e})()));
//# sourceMappingURL=vue-firewall.umd.min.js.map
\ No newline at end of file
diff --git a/src/www/js/vendor/vue-firewall.umd.min.js.map b/src/www/js/vendor/vue-firewall.umd.min.js.map
index 18385e15..35509ad0 100644
--- a/src/www/js/vendor/vue-firewall.umd.min.js.map
+++ b/src/www/js/vendor/vue-firewall.umd.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"vue-firewall.umd.min.js","mappings":"CAAA,SAA2CA,EAAMC,GAC1B,kBAAZC,SAA0C,kBAAXC,OACxCA,OAAOD,QAAUD,IACQ,oBAAXG,QAAyBA,OAAOC,IAC9CD,OAAO,GAAIH,GACe,kBAAZC,QACdA,QAAQ,eAAiBD,IAEzBD,EAAK,eAAiBC,GACvB,EATD,CASoB,qBAATK,KAAuBA,KAAOC,MAAO,I,mBCRhD,IAAIC,EAAsB,CAAC,E,MCA3BA,EAAoBC,EAAI,CAACP,EAASQ,KACjC,IAAI,IAAIC,KAAOD,EACXF,EAAoBI,EAAEF,EAAYC,KAASH,EAAoBI,EAAEV,EAASS,IAC5EE,OAAOC,eAAeZ,EAASS,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,C,WCNDH,EAAoBI,EAAI,CAACK,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,E,WCAlFV,EAAoBc,EAAI,E,cCGxB,G,uBAAsB,qBAAXC,OAAwB,CACjC,IAAIC,EAAgBD,OAAOE,SAASD,cAWhCE,EAAMF,GAAiBA,EAAcE,IAAIC,MAAM,2BAC/CD,IACF,IAA0BA,EAAI,GAElC,CCnBA,IAAIE,EAAS,WAAa,IAAIC,EAAItB,KAASuB,EAAGD,EAAIE,eAAmBC,EAAGH,EAAII,MAAMD,IAAIF,EAAG,OAAOE,EAAG,MAAM,CAACE,YAAY,qEAAqE,CAACF,EAAG,MAAM,CAACE,YAAY,yGAAyG,CAACF,EAAG,MAAM,CAACE,YAAY,aAAa,CAACF,EAAG,IAAI,CAACE,YAAY,8CAA8C,CAACL,EAAIM,GAAGN,EAAIO,GAAGP,EAAIQ,GAAG,oBAAoBL,EAAG,QAAQ,CAACE,YAAY,iDAAiD,CAACL,EAAIS,GAAG,GAAGN,EAAG,QAAQ,CAACE,YAAY,eAAeL,EAAIU,GAAIV,EAAc,YAAE,SAASW,EAAMC,GAAO,OAAOT,EAAG,KAAK,CAACrB,IAAI8B,GAAO,CAACT,EAAG,KAAK,CAACH,EAAIM,GAAGN,EAAIO,GAAGI,EAAME,SAASV,EAAG,KAAK,CAACH,EAAIM,GAAGN,EAAIO,GAAGI,EAAMG,SAASX,EAAG,KAAK,CAACH,EAAIM,GAAGN,EAAIO,GAAGI,EAAMI,UAAU,IAAG,KAAKf,EAAIS,GAAG,IAAI,EACnxBO,EAAkB,CAAC,WAAa,IAAIhB,EAAItB,KAASuB,EAAGD,EAAIE,eAAmBC,EAAGH,EAAII,MAAMD,IAAIF,EAAG,OAAOE,EAAG,QAAQ,CAACA,EAAG,KAAK,CAACA,EAAG,KAAK,CAACH,EAAIM,GAAG,eAAeH,EAAG,KAAK,CAACH,EAAIM,GAAG,kBAAkBH,EAAG,KAAK,CAACH,EAAIM,GAAG,qBAAqB,EAAE,WAAa,IAAIN,EAAItB,KAASuB,EAAGD,EAAIE,eAAmBC,EAAGH,EAAII,MAAMD,IAAIF,EAAG,OAAOE,EAAG,QAAQ,CAACE,YAAY,8EAA8E,CAACF,EAAG,QAAQ,CAACE,YAAY,gCAAgC,CAACF,EAAG,KAAK,CAACA,EAAG,KAAK,CAACH,EAAIM,GAAG,YAAYH,EAAG,KAAK,CAACE,YAAY,sCAAsC,CAACL,EAAIM,GAAG,YAAYH,EAAG,KAAK,CAACE,YAAY,sCAAsC,CAACL,EAAIM,GAAG,iBAAiBH,EAAG,KAAK,CAACE,YAAY,sCAAsC,CAACL,EAAIM,GAAG,cAAcH,EAAG,UAAUA,EAAG,QAAQ,CAACE,YAAY,eAAe,CAACF,EAAG,KAAK,CAACA,EAAG,KAAK,CAACE,YAAY,8BAA8B,CAACL,EAAIM,GAAG,YAAYH,EAAG,KAAK,CAACE,YAAY,8BAA8B,CAACL,EAAIM,GAAG,kBAAkBH,EAAG,KAAK,CAACE,YAAY,8BAA8B,CAACL,EAAIM,GAAG,cAAcH,EAAG,KAAK,CAACE,YAAY,8BAA8B,CAACL,EAAIM,GAAG,SAASH,EAAG,KAAK,CAACE,YAAY,iCAAiCF,EAAG,KAAK,CAACA,EAAG,KAAK,CAACE,YAAY,8BAA8B,CAACF,EAAG,OAAO,CAACc,MAAM,CAAC,GAAK,OAAO,CAACd,EAAG,QAAQ,CAACE,YAAY,iDAAiDY,MAAM,CAAC,KAAO,KAAK,KAAO,SAAS,MAAQ,cAAcd,EAAG,KAAK,CAACE,YAAY,0BAA0B,CAACF,EAAG,QAAQ,CAACE,YAAY,iDAAiDY,MAAM,CAAC,KAAO,KAAK,KAAO,OAAO,KAAO,cAAcd,EAAG,KAAK,CAACE,YAAY,0BAA0B,CAACF,EAAG,QAAQ,CAACE,YAAY,iDAAiDY,MAAM,CAAC,KAAO,KAAK,KAAO,OAAO,KAAO,mBAAmBd,EAAG,KAAK,CAACE,YAAY,0BAA0B,CAACF,EAAG,SAAS,CAACE,YAAY,iBAAiBY,MAAM,CAAC,KAAO,KAAK,KAAO,aAAa,CAACd,EAAG,SAAS,CAACc,MAAM,CAAC,MAAQ,QAAQ,CAACjB,EAAIM,GAAG,SAASH,EAAG,SAAS,CAACc,MAAM,CAAC,MAAQ,QAAQ,CAACjB,EAAIM,GAAG,aAAaH,EAAG,KAAK,CAACE,YAAY,8BAA8B,CAACF,EAAG,SAAS,CAACE,YAAY,iBAAiBY,MAAM,CAAC,KAAO,KAAK,KAAO,WAAW,CAACd,EAAG,SAAS,CAACc,MAAM,CAAC,MAAQ,UAAU,CAACjB,EAAIM,GAAG,WAAWH,EAAG,SAAS,CAACc,MAAM,CAAC,MAAQ,UAAU,CAACjB,EAAIM,GAAG,oBAAoB,GCAxrE,SACEO,KAAM,WACN,IAAAK,GACE,IAAIC,EAAa,GACjB,MAAO,CAAEA,aACX,EACAC,QAAS,CACP,aAAAC,GACE3C,KAAK4C,IAAID,gBAAgBE,MAAMJ,IAC7BzC,KAAKyC,WAAaA,CAAU,IAE3BK,OAAOC,IACNC,MAAMD,EAAIE,SAAWF,EAAIG,WAAW,GAE1C,GAEF,OAAAC,GACEnD,KAAK4C,IAAM,IAAIQ,IACfpD,KAAK2C,eACP,GCpBsP,ICMzO,SAASU,EACtBC,EACAjC,EACAiB,EACAiB,EACAC,EACAC,EACAC,EACAC,GAGA,IAoBIC,EApBAC,EACuB,oBAAlBP,EAA+BA,EAAcO,QAAUP,EAuDhE,GApDIjC,IACFwC,EAAQxC,OAASA,EACjBwC,EAAQvB,gBAAkBA,EAC1BuB,EAAQC,WAAY,GAIlBP,IACFM,EAAQE,YAAa,GAInBN,IACFI,EAAQG,SAAW,UAAYP,GAI7BC,GAEFE,EAAO,SAAUK,GAEfA,EACEA,GACCjE,KAAKkE,QAAUlE,KAAKkE,OAAOC,YAC3BnE,KAAKoE,QAAUpE,KAAKoE,OAAOF,QAAUlE,KAAKoE,OAAOF,OAAOC,WAEtDF,GAA0C,qBAAxBI,sBACrBJ,EAAUI,qBAGRb,GACFA,EAAa1C,KAAKd,KAAMiE,GAGtBA,GAAWA,EAAQK,uBACrBL,EAAQK,sBAAsBC,IAAIb,EAEtC,EAGAG,EAAQW,aAAeZ,GACdJ,IACTI,EAAOD,EACH,WACEH,EAAa1C,KACXd,MACC6D,EAAQE,WAAa/D,KAAKoE,OAASpE,MAAMyE,MAAMC,SAASC,WAE7D,EACAnB,GAGFI,EACF,GAAIC,EAAQE,WAAY,CAGtBF,EAAQe,cAAgBhB,EAExB,IAAIiB,EAAiBhB,EAAQxC,OAC7BwC,EAAQxC,OAAS,SAAkCyD,EAAGb,GAEpD,OADAL,EAAK9C,KAAKmD,GACHY,EAAeC,EAAGb,EAC3B,CACF,KAAO,CAEL,IAAIc,EAAWlB,EAAQmB,aACvBnB,EAAQmB,aAAeD,EAAW,GAAGE,OAAOF,EAAUnB,GAAQ,CAACA,EACjE,CAGF,MAAO,CACLjE,QAAS2D,EACTO,QAASA,EAEb,CCxFA,IAAIqB,EAAY,EACd,EACA7D,EACAiB,GACA,EACA,KACA,KACA,MAIF,QAAe4C,EAAiB,QChBhC,I","sources":["webpack://VueFirewall/webpack/universalModuleDefinition","webpack://VueFirewall/webpack/bootstrap","webpack://VueFirewall/webpack/runtime/define property getters","webpack://VueFirewall/webpack/runtime/hasOwnProperty shorthand","webpack://VueFirewall/webpack/runtime/publicPath","webpack://VueFirewall/../../../.local/share/pnpm/global/5/.pnpm/@vue+cli-service@5.0.8_lodash@4.17.21_webpack-sources@3.2.3/node_modules/@vue/cli-service/lib/commands/build/setPublicPath.js","webpack://VueFirewall/./www/templates/Firewall.vue?a453","webpack://VueFirewall/www/templates/Firewall.vue","webpack://VueFirewall/./www/templates/Firewall.vue?6878","webpack://VueFirewall/../../../.local/share/pnpm/global/5/.pnpm/vue-loader@15.11.1_css-loader@6.11.0_webpack@5.93.0__lodash@4.17.21_webpack@5.93.0/node_modules/vue-loader/lib/runtime/componentNormalizer.js","webpack://VueFirewall/./www/templates/Firewall.vue","webpack://VueFirewall/../../../.local/share/pnpm/global/5/.pnpm/@vue+cli-service@5.0.8_lodash@4.17.21_webpack-sources@3.2.3/node_modules/@vue/cli-service/lib/commands/build/entry-lib.js"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"VueFirewall\"] = factory();\n\telse\n\t\troot[\"VueFirewall\"] = factory();\n})((typeof self !== 'undefined' ? self : this), () => {\nreturn ","// The require scope\nvar __webpack_require__ = {};\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","__webpack_require__.p = \"\";","/* eslint-disable no-var */\n// This file is imported into lib/wc client bundles.\n\nif (typeof window !== 'undefined') {\n var currentScript = window.document.currentScript\n if (process.env.NEED_CURRENTSCRIPT_POLYFILL) {\n var getCurrentScript = require('@soda/get-current-script')\n currentScript = getCurrentScript()\n\n // for backward compatibility, because previously we directly included the polyfill\n if (!('currentScript' in document)) {\n Object.defineProperty(document, 'currentScript', { get: getCurrentScript })\n }\n }\n\n var src = currentScript && currentScript.src.match(/(.+\\/)[^/]+\\.js(\\?.*)?$/)\n if (src) {\n __webpack_public_path__ = src[1] // eslint-disable-line\n }\n}\n\n// Indicate to webpack that this file can be concatenated\nexport default null\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"shadow-md rounded-lg bg-white dark:bg-neutral-700 overflow-hidden\"},[_c('div',{staticClass:\"flex flex-row flex-auto items-center mb-4 p-3 px-5 border-b-2 border-gray-100 dark:border-neutral-600\"},[_c('div',{staticClass:\"flex-grow\"},[_c('p',{staticClass:\"text-2xl font-medium dark:text-neutral-200\"},[_vm._v(_vm._s(_vm.$t(\"firewall\")))])])]),_c('table',{staticClass:\"table-auto w-[70%] dark:text-neutral-200 mb-4\"},[_vm._m(0),_c('tbody',{staticClass:\"text-center\"},_vm._l((_vm.interfaces),function(iface,index){return _c('tr',{key:index},[_c('td',[_vm._v(_vm._s(iface.name))]),_c('td',[_vm._v(_vm._s(iface.ipv4))]),_c('td',[_vm._v(_vm._s(iface.ipv6))])])}),0)]),_vm._m(1)])}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('thead',[_c('tr',[_c('th',[_vm._v(\"Interface\")]),_c('th',[_vm._v(\"IPv4 address\")]),_c('th',[_vm._v(\"IPv6 address\")])])])},function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('table',{staticClass:\"table-auto border-t-2 dark:border-neutral-200 w-full dark:text-neutral-200\"},[_c('thead',{staticClass:\"bg-gray-200 dark:bg-gray-600\"},[_c('tr',[_c('th',[_vm._v(\"Action\")]),_c('th',{staticClass:\"border-x-2 dark:border-neutral-200\"},[_vm._v(\"Source\")]),_c('th',{staticClass:\"border-x-2 dark:border-neutral-200\"},[_vm._v(\"Destination\")]),_c('th',{staticClass:\"border-x-2 dark:border-neutral-200\"},[_vm._v(\"Protocol\")]),_c('th')])]),_c('tbody',{staticClass:\"text-center\"},[_c('tr',[_c('td',{staticClass:\"border border-gray-600 p-1\"},[_vm._v(\"delete\")]),_c('td',{staticClass:\"border border-gray-600 p-1\"},[_vm._v(\"192.168.11.3\")]),_c('td',{staticClass:\"border border-gray-600 p-1\"},[_vm._v(\"10.9.8.1\")]),_c('td',{staticClass:\"border border-gray-600 p-1\"},[_vm._v(\"udp\")]),_c('td',{staticClass:\"border border-gray-600 p-1\"})]),_c('tr',[_c('td',{staticClass:\"border border-gray-600 p-1\"},[_c('form',{attrs:{\"id\":\"fw\"}},[_c('input',{staticClass:\"w-full outline-none bg-transparent text-center\",attrs:{\"form\":\"fw\",\"type\":\"submit\",\"value\":\"send\"}})])]),_c('td',{staticClass:\"border border-gray-600\"},[_c('input',{staticClass:\"w-full outline-none bg-transparent text-center\",attrs:{\"form\":\"fw\",\"type\":\"text\",\"name\":\"source\"}})]),_c('td',{staticClass:\"border border-gray-600\"},[_c('input',{staticClass:\"w-full outline-none bg-transparent text-center\",attrs:{\"form\":\"fw\",\"type\":\"text\",\"name\":\"destination\"}})]),_c('td',{staticClass:\"border border-gray-600\"},[_c('select',{staticClass:\"bg-transparent\",attrs:{\"form\":\"fw\",\"name\":\"protocol\"}},[_c('option',{attrs:{\"value\":\"tcp\"}},[_vm._v(\"tcp\")]),_c('option',{attrs:{\"value\":\"udp\"}},[_vm._v(\"udp\")])])]),_c('td',{staticClass:\"border border-gray-600 p-1\"},[_c('select',{staticClass:\"bg-transparent\",attrs:{\"form\":\"fw\",\"name\":\"action\"}},[_c('option',{attrs:{\"value\":\"allow\"}},[_vm._v(\"allow\")]),_c('option',{attrs:{\"value\":\"block\"}},[_vm._v(\"block\")])])])])])])}]\n\nexport { render, staticRenderFns }","\n\n\n \n
\n
\n
{{ $t(\"firewall\") }}
\n
\n
\n\n
\n \n \n | Interface | \n IPv4 address | \n IPv6 address | \n
\n \n \n \n | {{ iface.name }} | \n {{ iface.ipv4 }} | \n {{ iface.ipv6 }} | \n
\n \n
\n\n
\n
\n\n","import mod from \"-!../../../../../.local/share/pnpm/global/5/.pnpm/vue-loader@15.11.1_css-loader@6.11.0_webpack@5.93.0__lodash@4.17.21_webpack@5.93.0/node_modules/vue-loader/lib/index.js??vue-loader-options!./Firewall.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../../../.local/share/pnpm/global/5/.pnpm/vue-loader@15.11.1_css-loader@6.11.0_webpack@5.93.0__lodash@4.17.21_webpack@5.93.0/node_modules/vue-loader/lib/index.js??vue-loader-options!./Firewall.vue?vue&type=script&lang=js\"","/* globals __VUE_SSR_CONTEXT__ */\n\n// IMPORTANT: Do NOT use ES2015 features in this file (except for modules).\n// This module is a runtime utility for cleaner component module output and will\n// be included in the final webpack user bundle.\n\nexport default function normalizeComponent(\n scriptExports,\n render,\n staticRenderFns,\n functionalTemplate,\n injectStyles,\n scopeId,\n moduleIdentifier /* server only */,\n shadowMode /* vue-cli only */\n) {\n // Vue.extend constructor export interop\n var options =\n typeof scriptExports === 'function' ? scriptExports.options : scriptExports\n\n // render functions\n if (render) {\n options.render = render\n options.staticRenderFns = staticRenderFns\n options._compiled = true\n }\n\n // functional template\n if (functionalTemplate) {\n options.functional = true\n }\n\n // scopedId\n if (scopeId) {\n options._scopeId = 'data-v-' + scopeId\n }\n\n var hook\n if (moduleIdentifier) {\n // server build\n hook = function (context) {\n // 2.3 injection\n context =\n context || // cached call\n (this.$vnode && this.$vnode.ssrContext) || // stateful\n (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext) // functional\n // 2.2 with runInNewContext: true\n if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {\n context = __VUE_SSR_CONTEXT__\n }\n // inject component styles\n if (injectStyles) {\n injectStyles.call(this, context)\n }\n // register component module identifier for async chunk inferrence\n if (context && context._registeredComponents) {\n context._registeredComponents.add(moduleIdentifier)\n }\n }\n // used by ssr in case component is cached and beforeCreate\n // never gets called\n options._ssrRegister = hook\n } else if (injectStyles) {\n hook = shadowMode\n ? function () {\n injectStyles.call(\n this,\n (options.functional ? this.parent : this).$root.$options.shadowRoot\n )\n }\n : injectStyles\n }\n\n if (hook) {\n if (options.functional) {\n // for template-only hot-reload because in that case the render fn doesn't\n // go through the normalizer\n options._injectStyles = hook\n // register for functional component in vue file\n var originalRender = options.render\n options.render = function renderWithStyleInjection(h, context) {\n hook.call(context)\n return originalRender(h, context)\n }\n } else {\n // inject component registration as beforeCreate hook\n var existing = options.beforeCreate\n options.beforeCreate = existing ? [].concat(existing, hook) : [hook]\n }\n }\n\n return {\n exports: scriptExports,\n options: options\n }\n}\n","import { render, staticRenderFns } from \"./Firewall.vue?vue&type=template&id=8bb350ba\"\nimport script from \"./Firewall.vue?vue&type=script&lang=js\"\nexport * from \"./Firewall.vue?vue&type=script&lang=js\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../../.local/share/pnpm/global/5/.pnpm/vue-loader@15.11.1_css-loader@6.11.0_webpack@5.93.0__lodash@4.17.21_webpack@5.93.0/node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports","import './setPublicPath'\nimport mod from '~entry'\nexport default mod\nexport * from '~entry'\n"],"names":["root","factory","exports","module","define","amd","self","this","__webpack_require__","d","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","p","window","currentScript","document","src","match","render","_vm","_h","$createElement","_c","_self","staticClass","_v","_s","$t","_m","_l","iface","index","name","ipv4","ipv6","staticRenderFns","attrs","data","interfaces","methods","getInterfaces","api","then","catch","err","alert","message","toString","mounted","API","normalizeComponent","scriptExports","functionalTemplate","injectStyles","scopeId","moduleIdentifier","shadowMode","hook","options","_compiled","functional","_scopeId","context","$vnode","ssrContext","parent","__VUE_SSR_CONTEXT__","_registeredComponents","add","_ssrRegister","$root","$options","shadowRoot","_injectStyles","originalRender","h","existing","beforeCreate","concat","component"],"sourceRoot":""}
\ No newline at end of file
+{"version":3,"file":"vue-firewall.umd.min.js","mappings":"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","sources":["webpack://VueFirewall/webpack/universalModuleDefinition","webpack://VueFirewall/webpack/bootstrap","webpack://VueFirewall/webpack/runtime/define property getters","webpack://VueFirewall/webpack/runtime/hasOwnProperty shorthand","webpack://VueFirewall/webpack/runtime/publicPath","webpack://VueFirewall/../../../.local/share/pnpm/global/5/.pnpm/@vue+cli-service@5.0.8_lodash@4.17.21_webpack-sources@3.2.3/node_modules/@vue/cli-service/lib/commands/build/setPublicPath.js","webpack://VueFirewall/./www/templates/Firewall.vue?8583","webpack://VueFirewall/www/templates/Firewall.vue","webpack://VueFirewall/./www/templates/Firewall.vue?6878","webpack://VueFirewall/../../../.local/share/pnpm/global/5/.pnpm/vue-loader@15.11.1_css-loader@6.11.0_webpack@5.93.0__lodash@4.17.21_webpack@5.93.0/node_modules/vue-loader/lib/runtime/componentNormalizer.js","webpack://VueFirewall/./www/templates/Firewall.vue","webpack://VueFirewall/../../../.local/share/pnpm/global/5/.pnpm/@vue+cli-service@5.0.8_lodash@4.17.21_webpack-sources@3.2.3/node_modules/@vue/cli-service/lib/commands/build/entry-lib.js"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"VueFirewall\"] = factory();\n\telse\n\t\troot[\"VueFirewall\"] = factory();\n})((typeof self !== 'undefined' ? self : this), () => {\nreturn ","// The require scope\nvar __webpack_require__ = {};\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","__webpack_require__.p = \"\";","/* eslint-disable no-var */\n// This file is imported into lib/wc client bundles.\n\nif (typeof window !== 'undefined') {\n var currentScript = window.document.currentScript\n if (process.env.NEED_CURRENTSCRIPT_POLYFILL) {\n var getCurrentScript = require('@soda/get-current-script')\n currentScript = getCurrentScript()\n\n // for backward compatibility, because previously we directly included the polyfill\n if (!('currentScript' in document)) {\n Object.defineProperty(document, 'currentScript', { get: getCurrentScript })\n }\n }\n\n var src = currentScript && currentScript.src.match(/(.+\\/)[^/]+\\.js(\\?.*)?$/)\n if (src) {\n __webpack_public_path__ = src[1] // eslint-disable-line\n }\n}\n\n// Indicate to webpack that this file can be concatenated\nexport default null\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"shadow-md rounded-lg bg-white dark:bg-neutral-700 overflow-hidden\"},[_c('div',{staticClass:\"flex flex-row flex-auto items-center mb-4 p-3 px-5 border-b-2 border-gray-100 dark:border-neutral-600\"},[_c('div',{staticClass:\"flex-grow\"},[_c('p',{staticClass:\"text-2xl font-medium dark:text-neutral-200\"},[_vm._v(_vm._s(_vm.$t(\"fwFirewall\")))])])]),_c('table',{staticClass:\"table-auto w-[70%] dark:text-neutral-200 mb-4\"},[_c('thead',[_c('tr',[_c('th',[_vm._v(_vm._s(_vm.$t('fwInterface')))]),_c('th',[_vm._v(_vm._s(_vm.$t('fwIv4')))]),_c('th',[_vm._v(_vm._s(_vm.$t('fwIv6')))])])]),_c('tbody',{staticClass:\"text-center\"},_vm._l((_vm.interfaces),function(iface,index){return _c('tr',{key:index},[_c('td',[_vm._v(_vm._s(iface.name))]),_c('td',[_vm._v(_vm._s(iface.ipv4))]),_c('td',[_vm._v(_vm._s(iface.ipv6))])])}),0)]),_c('table',{staticClass:\"table-auto border-t-2 dark:border-neutral-200 w-full dark:text-neutral-200\"},[_c('thead',{staticClass:\"bg-gray-200 dark:bg-gray-600\"},[_c('tr',[_c('th',[_vm._v(_vm._s(_vm.$t('fwAction')))]),_c('th',{staticClass:\"border-x-2 dark:border-neutral-200\"},[_vm._v(_vm._s(_vm.$t('fwSource')))]),_c('th',{staticClass:\"border-x-2 dark:border-neutral-200\"},[_vm._v(_vm._s(_vm.$t('fwDestination')))]),_c('th',{staticClass:\"border-x-2 dark:border-neutral-200\"},[_vm._v(_vm._s(_vm.$t('fwProtocol')))]),_c('th',[_vm._v(_vm._s(_vm.$t('fwTarget')))])])]),_c('tbody',{staticClass:\"text-center\"},[_vm._l((_vm.rules),function(rule,index){return _c('tr',{key:index},[_c('td',{staticClass:\"border border-gray-600 p-1 hover:bg-red-800 transition\"},[_c('button',{on:{\"click\":function($event){return _vm.deleteRule(rule.num)}}},[_c('svg',{staticClass:\"size-6\",attrs:{\"xmlns\":\"http://www.w3.org/2000/svg\",\"fill\":\"none\",\"viewBox\":\"0 0 24 24\",\"stroke-width\":\"1.5\",\"stroke\":\"currentColor\"}},[_c('path',{attrs:{\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\",\"d\":\"M6 18 18 6M6 6l12 12\"}})])])]),_c('td',{staticClass:\"border border-gray-600 p-1\"},[_vm._v(_vm._s(rule.source))]),_c('td',{staticClass:\"border border-gray-600 p-1\"},[_vm._v(_vm._s(rule.destination))]),_c('td',{staticClass:\"border border-gray-600 p-1\"},[_vm._v(_vm._s(rule.protocol))]),_c('td',{staticClass:\"border border-gray-600 p-1\"},[_vm._v(_vm._s(rule.target))])])}),_c('tr',[_c('td',{staticClass:\"border border-gray-600 p-1 hover:bg-green-600 transition\"},[_c('form',{attrs:{\"id\":\"fw\"},on:{\"submit\":_vm.addRule}},[_c('button',{attrs:{\"type\":\"submit\"}},[_c('svg',{staticClass:\"size-6\",attrs:{\"xmlns\":\"http://www.w3.org/2000/svg\",\"fill\":\"none\",\"viewBox\":\"0 0 24 24\",\"stroke-width\":\"1.5\",\"stroke\":\"currentColor\"}},[_c('path',{attrs:{\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\",\"d\":\"M12 9v6m3-3H9m12 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z\"}})])])])]),_c('td',{staticClass:\"border border-gray-600\"},[_c('input',{directives:[{name:\"model\",rawName:\"v-model\",value:(_vm.newRule.source),expression:\"newRule.source\"}],staticClass:\"w-full outline-none bg-transparent text-center\",attrs:{\"form\":\"fw\",\"type\":\"text\",\"name\":\"source\"},domProps:{\"value\":(_vm.newRule.source)},on:{\"input\":function($event){if($event.target.composing){ return; }_vm.$set(_vm.newRule, \"source\", $event.target.value)}}})]),_c('td',{staticClass:\"border border-gray-600\"},[_c('input',{directives:[{name:\"model\",rawName:\"v-model\",value:(_vm.newRule.destination),expression:\"newRule.destination\"}],staticClass:\"w-full outline-none bg-transparent text-center\",attrs:{\"form\":\"fw\",\"type\":\"text\",\"name\":\"destination\"},domProps:{\"value\":(_vm.newRule.destination)},on:{\"input\":function($event){if($event.target.composing){ return; }_vm.$set(_vm.newRule, \"destination\", $event.target.value)}}})]),_c('td',{staticClass:\"border border-gray-600\"},[_c('select',{directives:[{name:\"model\",rawName:\"v-model\",value:(_vm.newRule.protocol),expression:\"newRule.protocol\"}],staticClass:\"bg-transparent\",attrs:{\"form\":\"fw\",\"name\":\"protocol\"},on:{\"change\":function($event){var $$selectedVal = Array.prototype.filter.call($event.target.options,function(o){return o.selected}).map(function(o){var val = \"_value\" in o ? o._value : o.value;return val}); _vm.$set(_vm.newRule, \"protocol\", $event.target.multiple ? $$selectedVal : $$selectedVal[0])}}},[_c('option',{attrs:{\"value\":\"tcp\"}},[_vm._v(\"TCP\")]),_c('option',{attrs:{\"value\":\"udp\"}},[_vm._v(\"UDP\")])])]),_c('td',{staticClass:\"border border-gray-600 p-1\"},[_c('select',{directives:[{name:\"model\",rawName:\"v-model\",value:(_vm.newRule.target),expression:\"newRule.target\"}],staticClass:\"bg-transparent\",attrs:{\"form\":\"fw\",\"name\":\"target\"},on:{\"change\":function($event){var $$selectedVal = Array.prototype.filter.call($event.target.options,function(o){return o.selected}).map(function(o){var val = \"_value\" in o ? o._value : o.value;return val}); _vm.$set(_vm.newRule, \"target\", $event.target.multiple ? $$selectedVal : $$selectedVal[0])}}},[_c('option',{attrs:{\"value\":\"ACCEPT\"}},[_vm._v(\"ALLOW\")]),_c('option',{attrs:{\"value\":\"DROP\"}},[_vm._v(\"BLOCK\")])])])])],2)])])}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n\n \n
\n
\n
{{ $t(\"fwFirewall\") }}
\n
\n
\n\n
\n \n \n | {{ $t('fwInterface') }} | \n {{ $t('fwIv4') }} | \n {{ $t('fwIv6') }} | \n
\n \n \n \n | {{ iface.name }} | \n {{ iface.ipv4 }} | \n {{ iface.ipv6 }} | \n
\n \n
\n\n
\n
\n\n","import mod from \"-!../../../../../.local/share/pnpm/global/5/.pnpm/vue-loader@15.11.1_css-loader@6.11.0_webpack@5.93.0__lodash@4.17.21_webpack@5.93.0/node_modules/vue-loader/lib/index.js??vue-loader-options!./Firewall.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../../../.local/share/pnpm/global/5/.pnpm/vue-loader@15.11.1_css-loader@6.11.0_webpack@5.93.0__lodash@4.17.21_webpack@5.93.0/node_modules/vue-loader/lib/index.js??vue-loader-options!./Firewall.vue?vue&type=script&lang=js\"","/* globals __VUE_SSR_CONTEXT__ */\n\n// IMPORTANT: Do NOT use ES2015 features in this file (except for modules).\n// This module is a runtime utility for cleaner component module output and will\n// be included in the final webpack user bundle.\n\nexport default function normalizeComponent(\n scriptExports,\n render,\n staticRenderFns,\n functionalTemplate,\n injectStyles,\n scopeId,\n moduleIdentifier /* server only */,\n shadowMode /* vue-cli only */\n) {\n // Vue.extend constructor export interop\n var options =\n typeof scriptExports === 'function' ? scriptExports.options : scriptExports\n\n // render functions\n if (render) {\n options.render = render\n options.staticRenderFns = staticRenderFns\n options._compiled = true\n }\n\n // functional template\n if (functionalTemplate) {\n options.functional = true\n }\n\n // scopedId\n if (scopeId) {\n options._scopeId = 'data-v-' + scopeId\n }\n\n var hook\n if (moduleIdentifier) {\n // server build\n hook = function (context) {\n // 2.3 injection\n context =\n context || // cached call\n (this.$vnode && this.$vnode.ssrContext) || // stateful\n (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext) // functional\n // 2.2 with runInNewContext: true\n if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {\n context = __VUE_SSR_CONTEXT__\n }\n // inject component styles\n if (injectStyles) {\n injectStyles.call(this, context)\n }\n // register component module identifier for async chunk inferrence\n if (context && context._registeredComponents) {\n context._registeredComponents.add(moduleIdentifier)\n }\n }\n // used by ssr in case component is cached and beforeCreate\n // never gets called\n options._ssrRegister = hook\n } else if (injectStyles) {\n hook = shadowMode\n ? function () {\n injectStyles.call(\n this,\n (options.functional ? this.parent : this).$root.$options.shadowRoot\n )\n }\n : injectStyles\n }\n\n if (hook) {\n if (options.functional) {\n // for template-only hot-reload because in that case the render fn doesn't\n // go through the normalizer\n options._injectStyles = hook\n // register for functional component in vue file\n var originalRender = options.render\n options.render = function renderWithStyleInjection(h, context) {\n hook.call(context)\n return originalRender(h, context)\n }\n } else {\n // inject component registration as beforeCreate hook\n var existing = options.beforeCreate\n options.beforeCreate = existing ? [].concat(existing, hook) : [hook]\n }\n }\n\n return {\n exports: scriptExports,\n options: options\n }\n}\n","import { render, staticRenderFns } from \"./Firewall.vue?vue&type=template&id=3e0830ea\"\nimport script from \"./Firewall.vue?vue&type=script&lang=js\"\nexport * from \"./Firewall.vue?vue&type=script&lang=js\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../../.local/share/pnpm/global/5/.pnpm/vue-loader@15.11.1_css-loader@6.11.0_webpack@5.93.0__lodash@4.17.21_webpack@5.93.0/node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports","import './setPublicPath'\nimport mod from '~entry'\nexport default mod\nexport * from '~entry'\n"],"names":["root","factory","exports","module","define","amd","self","this","__webpack_require__","d","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","p","window","currentScript","document","src","match","render","_vm","_h","$createElement","_c","_self","staticClass","_v","_s","$t","_l","iface","index","name","ipv4","ipv6","rule","on","$event","deleteRule","num","attrs","source","destination","protocol","target","addRule","directives","rawName","value","newRule","expression","domProps","composing","$set","$$selectedVal","Array","filter","options","selected","map","val","_value","multiple","staticRenderFns","data","interfaces","rules","methods","getInterfaces","api","then","catch","err","alert","message","toString","getRules","e","preventDefault","mounted","API","normalizeComponent","scriptExports","functionalTemplate","injectStyles","scopeId","moduleIdentifier","shadowMode","hook","_compiled","functional","_scopeId","context","$vnode","ssrContext","parent","__VUE_SSR_CONTEXT__","_registeredComponents","add","_ssrRegister","$root","$options","shadowRoot","_injectStyles","originalRender","h","existing","beforeCreate","concat","component"],"sourceRoot":""}
\ No newline at end of file
diff --git a/src/www/templates/Firewall.vue b/src/www/templates/Firewall.vue
index e5b524a5..bc497782 100644
--- a/src/www/templates/Firewall.vue
+++ b/src/www/templates/Firewall.vue
@@ -3,7 +3,14 @@ export default {
name: 'Firewall',
data() {
let interfaces = [];
- return { interfaces };
+ let rules = [];
+ let newRule = {
+ source: '',
+ destination: '',
+ protocol: '',
+ target: '',
+ };
+ return { interfaces, rules, newRule };
},
methods: {
getInterfaces() {
@@ -13,11 +20,44 @@ export default {
.catch((err) => {
alert(err.message || err.toString());
})
- }
+ },
+ getRules() {
+ this.api.getRules().then((rules) => {
+ this.rules = rules;
+ })
+ .catch((err) => {
+ alert(err.message || err.toString());
+ })
+ },
+ addRule(e) {
+ e.preventDefault();
+
+ const { source, destination, protocol, target } = this.newRule;
+ this.api.addRule({ source, destination, protocol, target }).then(() => {
+ this.getRules();
+ }).then(() => {
+ this.newRule = {
+ source: '',
+ destination: '',
+ protocol: '',
+ target: '',
+ };
+ }).catch((err) => {
+ alert(err.message || err.toString());
+ });
+ },
+ deleteRule(num) {
+ this.api.deleteRule({ num }).then(() => {
+ this.getRules();
+ }).catch((err) => {
+ alert(err.message || err.toString());
+ });
+ },
},
mounted() {
this.api = new API();
this.getInterfaces();
+ this.getRules();
}
}
@@ -26,16 +66,16 @@ export default {
-
{{ $t("firewall") }}
+
{{ $t("fwFirewall") }}
- | Interface |
- IPv4 address |
- IPv6 address |
+ {{ $t('fwInterface') }} |
+ {{ $t('fwIv4') }} |
+ {{ $t('fwIv6') }} |
@@ -50,43 +90,58 @@ export default {
- | Action |
- Source |
- Destination |
- Protocol |
- |
+ {{ $t('fwAction') }} |
+ {{ $t('fwSource') }} |
+ {{ $t('fwDestination') }} |
+ {{ $t('fwProtocol') }} |
+ {{ $t('fwTarget') }} |
-
- | delete |
- 192.168.11.3 |
- 10.9.8.1 |
- udp |
- |
+
+ |
+
+ |
+ {{ rule.source }} |
+ {{ rule.destination }} |
+ {{ rule.protocol }} |
+ {{ rule.target }} |
- |
- |