Просмотр исходного кода

feat(firewall): add Src. and Dst. Geo Location matchers to General tab in Filter, NAT, and Mangle modals

Proxmox Router 1 неделя назад
Родитель
Сommit
77eca22f05
2 измененных файлов с 130 добавлено и 4 удалено
  1. 33 3
      internal/web/static/app.js
  2. 97 1
      internal/web/static/index.html

+ 33 - 3
internal/web/static/app.js

@@ -2960,9 +2960,11 @@ function openAddFilterModal() {
   populateInterfaceSelect('fw-val-outiface');
   populateAddressListSelect('fw-val-srclist');
   populateAddressListSelect('fw-val-dstlist');
+  populateGeoIPSelect('fw-val-srcgeo');
+  populateGeoIPSelect('fw-val-dstgeo');
 
   const allFieldKeys = [
-    'src', 'dst', 'srclist', 'dstlist', 'proto', 'sport', 'dport', 'anyport',
+    'src', 'dst', 'srclist', 'dstlist', 'srcgeo', 'dstgeo', 'proto', 'sport', 'dport', 'anyport',
     'iniface', 'outiface', 'inifacelist', 'outifacelist', 'pktmark', 'connmark',
     'routingmark', 'conntype', 'cs', 'natstate',
     'layer7', 'content', 'connbytes', 'connrate', 'pcc', 'srcmac',
@@ -2998,11 +3000,15 @@ function openEditFilterModal(id) {
   populateInterfaceSelect('fw-val-outiface', (r.out_interface || '').replace(/^!/, ''));
   populateAddressListSelect('fw-val-srclist', (r.src_address_list || '').replace(/^!/, ''));
   populateAddressListSelect('fw-val-dstlist', (r.dst_address_list || '').replace(/^!/, ''));
+  populateGeoIPSelect('fw-val-srcgeo', r.src_geoip || '');
+  populateGeoIPSelect('fw-val-dstgeo', r.dst_geoip || '');
 
   setFwFieldVal('src', r.src_address, true);
   setFwFieldVal('dst', r.dst_address, true);
   setFwFieldVal('srclist', r.src_address_list, true);
   setFwFieldVal('dstlist', r.dst_address_list, true);
+  setFwFieldVal('srcgeo', r.src_geoip, true);
+  setFwFieldVal('dstgeo', r.dst_geoip, true);
   if (r.protocol && r.protocol !== 'all') {
     setFwFieldVal('proto', r.protocol, true);
   } else {
@@ -3208,6 +3214,8 @@ async function applyFilterRule(closeAfter = false) {
   const dst = getFwFieldVal('dst', true);
   const srclist = getFwFieldVal('srclist', true);
   const dstlist = getFwFieldVal('dstlist', true);
+  const srcgeo = getFwFieldVal('srcgeo', true);
+  const dstgeo = getFwFieldVal('dstgeo', true);
   const proto = getFwFieldVal('proto', true);
   const sport = getFwFieldVal('sport', true);
   const dport = getFwFieldVal('dport', true);
@@ -3260,6 +3268,8 @@ async function applyFilterRule(closeAfter = false) {
     connection_nat_state: natStates,
     src_address_list: srclist,
     dst_address_list: dstlist,
+    src_geoip: srcgeo,
+    dst_geoip: dstgeo,
     comment,
     disabled: !enabled,
 
@@ -3730,9 +3740,11 @@ function openAddNATModal() {
   populateInterfaceSelect('nat-val-outiface');
   populateAddressListSelect('nat-val-srclist');
   populateAddressListSelect('nat-val-dstlist');
+  populateGeoIPSelect('nat-val-srcgeo');
+  populateGeoIPSelect('nat-val-dstgeo');
 
   const allFieldKeys = [
-    'src', 'dst', 'srclist', 'dstlist', 'proto', 'sport', 'dport', 'anyport',
+    'src', 'dst', 'srclist', 'dstlist', 'srcgeo', 'dstgeo', 'proto', 'sport', 'dport', 'anyport',
     'iniface', 'outiface', 'inifacelist', 'outifacelist', 'pktmark', 'connmark',
     'routingmark', 'conntype',
     'layer7', 'content', 'connbytes', 'connrate', 'pcc', 'srcmac',
@@ -3770,11 +3782,15 @@ function openEditNATModal(id) {
   populateInterfaceSelect('nat-val-outiface', (r.out_interface || '').replace(/^!/, ''));
   populateAddressListSelect('nat-val-srclist', (r.src_address_list || '').replace(/^!/, ''));
   populateAddressListSelect('nat-val-dstlist', (r.dst_address_list || '').replace(/^!/, ''));
+  populateGeoIPSelect('nat-val-srcgeo', r.src_geoip || '');
+  populateGeoIPSelect('nat-val-dstgeo', r.dst_geoip || '');
 
   setNATFieldVal('src', r.src_address, true);
   setNATFieldVal('dst', r.dst_address, true);
   setNATFieldVal('srclist', r.src_address_list, true);
   setNATFieldVal('dstlist', r.dst_address_list, true);
+  setNATFieldVal('srcgeo', r.src_geoip, true);
+  setNATFieldVal('dstgeo', r.dst_geoip, true);
   if (r.protocol && r.protocol !== 'all') {
     setNATFieldVal('proto', r.protocol, true);
   } else {
@@ -3907,6 +3923,8 @@ async function applyNATRule(closeAfter = false) {
   const dst = getNATFieldVal('dst', true);
   const srclist = getNATFieldVal('srclist', true);
   const dstlist = getNATFieldVal('dstlist', true);
+  const srcgeo = getNATFieldVal('srcgeo', true);
+  const dstgeo = getNATFieldVal('dstgeo', true);
   const proto = getNATFieldVal('proto', true);
   const sport = getNATFieldVal('sport', true);
   const dport = getNATFieldVal('dport', true);
@@ -3945,6 +3963,8 @@ async function applyNATRule(closeAfter = false) {
     connection_type: conntype,
     src_address_list: srclist,
     dst_address_list: dstlist,
+    src_geoip: srcgeo,
+    dst_geoip: dstgeo,
     comment,
     disabled: !enabled,
 
@@ -4356,7 +4376,7 @@ function toggleMangleLogPrefix() {
 }
 
 const allMangleFieldKeys = [
-  'src', 'dst', 'srclist', 'dstlist', 'proto', 'sport', 'dport', 'anyport',
+  'src', 'dst', 'srclist', 'dstlist', 'srcgeo', 'dstgeo', 'proto', 'sport', 'dport', 'anyport',
   'iniface', 'outiface', 'inifacelist', 'outifacelist', 'pktmark', 'connmark',
   'routingmark', 'conntype', 'cs', 'natstate',
   'layer7', 'content', 'connbytes', 'connrate', 'pcc', 'srcmac',
@@ -4396,6 +4416,8 @@ function openAddMangleModal() {
   populateInterfaceSelect('mangle-val-outiface');
   populateAddressListSelect('mangle-val-srclist');
   populateAddressListSelect('mangle-val-dstlist');
+  populateGeoIPSelect('mangle-val-srcgeo');
+  populateGeoIPSelect('mangle-val-dstgeo');
 
   allMangleFieldKeys.forEach(k => toggleMangleField(k, false));
 
@@ -4438,11 +4460,15 @@ function openEditMangleModal(id) {
   populateInterfaceSelect('mangle-val-outiface', (r.out_interface || '').replace(/^!/, ''));
   populateAddressListSelect('mangle-val-srclist', (r.src_address_list || '').replace(/^!/, ''));
   populateAddressListSelect('mangle-val-dstlist', (r.dst_address_list || '').replace(/^!/, ''));
+  populateGeoIPSelect('mangle-val-srcgeo', r.src_geoip || '');
+  populateGeoIPSelect('mangle-val-dstgeo', r.dst_geoip || '');
 
   setMangleFieldVal('src', r.src_address, true);
   setMangleFieldVal('dst', r.dst_address, true);
   setMangleFieldVal('srclist', r.src_address_list, true);
   setMangleFieldVal('dstlist', r.dst_address_list, true);
+  setMangleFieldVal('srcgeo', r.src_geoip, true);
+  setMangleFieldVal('dstgeo', r.dst_geoip, true);
   if (r.protocol && r.protocol !== 'all') {
     setMangleFieldVal('proto', r.protocol, true);
   } else {
@@ -4598,6 +4624,8 @@ async function applyMangleRule(closeAfter = false) {
   const dst = getMangleFieldVal('dst', true);
   const srclist = getMangleFieldVal('srclist', true);
   const dstlist = getMangleFieldVal('dstlist', true);
+  const srcgeo = getMangleFieldVal('srcgeo', true);
+  const dstgeo = getMangleFieldVal('dstgeo', true);
   const proto = getMangleFieldVal('proto', true);
   const sport = getMangleFieldVal('sport', true);
   const dport = getMangleFieldVal('dport', true);
@@ -4649,6 +4677,8 @@ async function applyMangleRule(closeAfter = false) {
     connection_nat_state: natStates,
     src_address_list: srclist,
     dst_address_list: dstlist,
+    src_geoip: srcgeo,
+    dst_geoip: dstgeo,
     comment,
     disabled: !enabled,
 

+ 97 - 1
internal/web/static/index.html

@@ -3498,6 +3498,38 @@
               </div>
             </div>
 
+            <!-- Src. Geo Location -->
+            <div class="flex items-center text-xs py-1" id="fw-row-srcgeo">
+              <label class="w-36 sm:w-44 text-right pr-3.5 text-slate-300 shrink-0 select-none">Src. Geo Location</label>
+              <div class="flex-1 flex items-center gap-1.5 min-w-0">
+                <button type="button" onclick="toggleFwField('srcgeo', true)" id="fw-plus-srcgeo" class="w-5 h-5 flex items-center justify-center bg-[#172435] hover:bg-[#1e3047] border border-[#2b3e56] rounded text-slate-300 hover:text-sky-300 text-xs font-bold leading-none">+</button>
+                <div id="fw-field-srcgeo" class="hidden flex-1 flex items-center gap-1.5 min-w-0">
+                  <label title="Invert match (!)" class="flex items-center gap-1 cursor-pointer pr-1 select-none">
+                    <input type="checkbox" id="fw-inv-srcgeo" class="rounded bg-[#101721] border-[#2b3e56] text-amber-500 focus:ring-0 w-3.5 h-3.5">
+                    <span class="font-mono font-bold text-amber-400 text-xs">!</span>
+                  </label>
+                  <select id="fw-val-srcgeo" class="bg-[#15202e] border border-[#26374d] rounded px-2.5 py-1 text-xs text-white font-mono focus:outline-none focus:border-sky-500 w-full"></select>
+                  <button type="button" onclick="toggleFwField('srcgeo', false)" class="w-5 h-5 flex items-center justify-center text-slate-500 hover:text-rose-400 text-xs font-bold leading-none shrink-0" title="Remove / Clear">-</button>
+                </div>
+              </div>
+            </div>
+
+            <!-- Dst. Geo Location -->
+            <div class="flex items-center text-xs py-1" id="fw-row-dstgeo">
+              <label class="w-36 sm:w-44 text-right pr-3.5 text-slate-300 shrink-0 select-none">Dst. Geo Location</label>
+              <div class="flex-1 flex items-center gap-1.5 min-w-0">
+                <button type="button" onclick="toggleFwField('dstgeo', true)" id="fw-plus-dstgeo" class="w-5 h-5 flex items-center justify-center bg-[#172435] hover:bg-[#1e3047] border border-[#2b3e56] rounded text-slate-300 hover:text-sky-300 text-xs font-bold leading-none">+</button>
+                <div id="fw-field-dstgeo" class="hidden flex-1 flex items-center gap-1.5 min-w-0">
+                  <label title="Invert match (!)" class="flex items-center gap-1 cursor-pointer pr-1 select-none">
+                    <input type="checkbox" id="fw-inv-dstgeo" class="rounded bg-[#101721] border-[#2b3e56] text-amber-500 focus:ring-0 w-3.5 h-3.5">
+                    <span class="font-mono font-bold text-amber-400 text-xs">!</span>
+                  </label>
+                  <select id="fw-val-dstgeo" class="bg-[#15202e] border border-[#26374d] rounded px-2.5 py-1 text-xs text-white font-mono focus:outline-none focus:border-sky-500 w-full"></select>
+                  <button type="button" onclick="toggleFwField('dstgeo', false)" class="w-5 h-5 flex items-center justify-center text-slate-500 hover:text-rose-400 text-xs font-bold leading-none shrink-0" title="Remove / Clear">-</button>
+                </div>
+              </div>
+            </div>
+
             <hr class="border-[#213042] my-2">
 
             <!-- Protocol -->
@@ -4443,6 +4475,38 @@
               </div>
             </div>
 
+            <!-- Src. Geo Location -->
+            <div class="flex items-center text-xs py-1" id="nat-row-srcgeo">
+              <label class="w-36 sm:w-44 text-right pr-3.5 text-slate-300 shrink-0 select-none">Src. Geo Location</label>
+              <div class="flex-1 flex items-center gap-1.5 min-w-0">
+                <button type="button" onclick="toggleNATField('srcgeo', true)" id="nat-plus-srcgeo" class="w-5 h-5 flex items-center justify-center bg-[#172435] hover:bg-[#1e3047] border border-[#2b3e56] rounded text-slate-300 hover:text-sky-300 text-xs font-bold leading-none">+</button>
+                <div id="nat-field-srcgeo" class="hidden flex-1 flex items-center gap-1.5 min-w-0">
+                  <label title="Invert match (!)" class="flex items-center gap-1 cursor-pointer pr-1 select-none">
+                    <input type="checkbox" id="nat-inv-srcgeo" class="rounded bg-[#101721] border-[#2b3e56] text-amber-500 focus:ring-0 w-3.5 h-3.5">
+                    <span class="font-mono font-bold text-amber-400 text-xs">!</span>
+                  </label>
+                  <select id="nat-val-srcgeo" class="bg-[#15202e] border border-[#26374d] rounded px-2.5 py-1 text-xs text-white font-mono focus:outline-none focus:border-sky-500 w-full"></select>
+                  <button type="button" onclick="toggleNATField('srcgeo', false)" class="w-5 h-5 flex items-center justify-center text-slate-500 hover:text-rose-400 text-xs font-bold leading-none shrink-0" title="Remove / Clear">-</button>
+                </div>
+              </div>
+            </div>
+
+            <!-- Dst. Geo Location -->
+            <div class="flex items-center text-xs py-1" id="nat-row-dstgeo">
+              <label class="w-36 sm:w-44 text-right pr-3.5 text-slate-300 shrink-0 select-none">Dst. Geo Location</label>
+              <div class="flex-1 flex items-center gap-1.5 min-w-0">
+                <button type="button" onclick="toggleNATField('dstgeo', true)" id="nat-plus-dstgeo" class="w-5 h-5 flex items-center justify-center bg-[#172435] hover:bg-[#1e3047] border border-[#2b3e56] rounded text-slate-300 hover:text-sky-300 text-xs font-bold leading-none">+</button>
+                <div id="nat-field-dstgeo" class="hidden flex-1 flex items-center gap-1.5 min-w-0">
+                  <label title="Invert match (!)" class="flex items-center gap-1 cursor-pointer pr-1 select-none">
+                    <input type="checkbox" id="nat-inv-dstgeo" class="rounded bg-[#101721] border-[#2b3e56] text-amber-500 focus:ring-0 w-3.5 h-3.5">
+                    <span class="font-mono font-bold text-amber-400 text-xs">!</span>
+                  </label>
+                  <select id="nat-val-dstgeo" class="bg-[#15202e] border border-[#26374d] rounded px-2.5 py-1 text-xs text-white font-mono focus:outline-none focus:border-sky-500 w-full"></select>
+                  <button type="button" onclick="toggleNATField('dstgeo', false)" class="w-5 h-5 flex items-center justify-center text-slate-500 hover:text-rose-400 text-xs font-bold leading-none shrink-0" title="Remove / Clear">-</button>
+                </div>
+              </div>
+            </div>
+
             <hr class="border-[#213042] my-2">
 
             <!-- Protocol -->
@@ -5342,6 +5406,38 @@
               </div>
             </div>
 
+            <!-- Src. Geo Location -->
+            <div class="flex items-center text-xs py-1" id="mangle-row-srcgeo">
+              <label class="w-36 sm:w-44 text-right pr-3.5 text-slate-300 shrink-0 select-none">Src. Geo Location</label>
+              <div class="flex-1 flex items-center gap-1.5 min-w-0">
+                <button type="button" onclick="toggleMangleField('srcgeo', true)" id="mangle-plus-srcgeo" class="w-5 h-5 flex items-center justify-center bg-[#172435] hover:bg-[#1e3047] border border-[#2b3e56] rounded text-slate-300 hover:text-sky-300 text-xs font-bold leading-none">+</button>
+                <div id="mangle-field-srcgeo" class="hidden flex-1 flex items-center gap-1.5 min-w-0">
+                  <label title="Invert match (!)" class="flex items-center gap-1 cursor-pointer pr-1 select-none">
+                    <input type="checkbox" id="mangle-inv-srcgeo" class="rounded bg-[#101721] border-[#2b3e56] text-amber-500 focus:ring-0 w-3.5 h-3.5">
+                    <span class="font-mono font-bold text-amber-400 text-xs">!</span>
+                  </label>
+                  <select id="mangle-val-srcgeo" class="bg-[#15202e] border border-[#26374d] rounded px-2.5 py-1 text-xs text-white font-mono focus:outline-none focus:border-sky-500 w-full"></select>
+                  <button type="button" onclick="toggleMangleField('srcgeo', false)" class="w-5 h-5 flex items-center justify-center text-slate-500 hover:text-rose-400 text-xs font-bold leading-none shrink-0" title="Remove / Clear">-</button>
+                </div>
+              </div>
+            </div>
+
+            <!-- Dst. Geo Location -->
+            <div class="flex items-center text-xs py-1" id="mangle-row-dstgeo">
+              <label class="w-36 sm:w-44 text-right pr-3.5 text-slate-300 shrink-0 select-none">Dst. Geo Location</label>
+              <div class="flex-1 flex items-center gap-1.5 min-w-0">
+                <button type="button" onclick="toggleMangleField('dstgeo', true)" id="mangle-plus-dstgeo" class="w-5 h-5 flex items-center justify-center bg-[#172435] hover:bg-[#1e3047] border border-[#2b3e56] rounded text-slate-300 hover:text-sky-300 text-xs font-bold leading-none">+</button>
+                <div id="mangle-field-dstgeo" class="hidden flex-1 flex items-center gap-1.5 min-w-0">
+                  <label title="Invert match (!)" class="flex items-center gap-1 cursor-pointer pr-1 select-none">
+                    <input type="checkbox" id="mangle-inv-dstgeo" class="rounded bg-[#101721] border-[#2b3e56] text-amber-500 focus:ring-0 w-3.5 h-3.5">
+                    <span class="font-mono font-bold text-amber-400 text-xs">!</span>
+                  </label>
+                  <select id="mangle-val-dstgeo" class="bg-[#15202e] border border-[#26374d] rounded px-2.5 py-1 text-xs text-white font-mono focus:outline-none focus:border-sky-500 w-full"></select>
+                  <button type="button" onclick="toggleMangleField('dstgeo', false)" class="w-5 h-5 flex items-center justify-center text-slate-500 hover:text-rose-400 text-xs font-bold leading-none shrink-0" title="Remove / Clear">-</button>
+                </div>
+              </div>
+            </div>
+
             <hr class="border-[#213042] my-2">
 
             <!-- Protocol -->
@@ -7631,6 +7727,6 @@
   </div>
 
   <datalist id="fw-addrlist-datalist"></datalist>
-  <script src="app.js?v=5.3"></script>
+  <script src="app.js?v=5.4"></script>
 </body>
 </html>