mirror of
https://github.com/vincentmli/bpfire.git
synced 2026-04-14 13:02:58 +02:00
Compare commits
293 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d7d0967f9e | ||
|
|
4382757dff | ||
|
|
d38d3d5d6e | ||
|
|
2ab05a1533 | ||
|
|
ecae6bb08c | ||
|
|
704a226f1f | ||
|
|
916a8aa5ed | ||
|
|
58b4babde2 | ||
|
|
101831d1b7 | ||
|
|
0b4a8acd52 | ||
|
|
04033ad1a5 | ||
|
|
c16b669813 | ||
|
|
587de19dca | ||
|
|
61deed354b | ||
|
|
3055fec1b6 | ||
|
|
fd6cd41a95 | ||
|
|
27092cf180 | ||
|
|
537587ae64 | ||
|
|
e44245f5fb | ||
|
|
3a815d1814 | ||
|
|
13dfd638bf | ||
|
|
575b5b2535 | ||
|
|
a931d86850 | ||
|
|
aba6bc1e84 | ||
|
|
993dbbbd75 | ||
|
|
a8d93e014d | ||
|
|
a8dc9235f1 | ||
|
|
0e302b1efc | ||
|
|
578eb58ea0 | ||
|
|
a81b1f8f2b | ||
|
|
ca64eb8761 | ||
|
|
8d0051d8f6 | ||
|
|
06359e6db4 | ||
|
|
4045f9fbc2 | ||
|
|
1475ef5093 | ||
|
|
351e665042 | ||
|
|
c7e72c51bf | ||
|
|
ec74268fa7 | ||
|
|
f09bba1d6c | ||
|
|
8462438396 | ||
|
|
557fc6ec81 | ||
|
|
4885bc8554 | ||
|
|
a3f7758510 | ||
|
|
67d1b8a4e9 | ||
|
|
d1d79d74e5 | ||
|
|
a989b976cb | ||
|
|
5ea3369a44 | ||
|
|
97e543817a | ||
|
|
7b0cc24bbf | ||
|
|
d270ada82c | ||
|
|
4e61b8bef9 | ||
|
|
03efd275ec | ||
|
|
2580c06cb7 | ||
|
|
aff726b928 | ||
|
|
6ed934dbfc | ||
|
|
638483ff08 | ||
|
|
3710ff2af7 | ||
|
|
3eb0ec8b1b | ||
|
|
2d55d3c672 | ||
|
|
0f4e6612df | ||
|
|
90a4a51a0e | ||
|
|
3745fdcb6a | ||
|
|
e9c5334eeb | ||
|
|
3a8cd99ef1 | ||
|
|
c74e903b32 | ||
|
|
d854559daf | ||
|
|
dd9a60e720 | ||
|
|
d30518a04a | ||
|
|
4e665f6a3c | ||
|
|
279f1e8e86 | ||
|
|
b78ee945cd | ||
|
|
d81f2b838e | ||
|
|
e51ee79752 | ||
|
|
3132f7bc78 | ||
|
|
2e3ea0ae64 | ||
|
|
9d50babeb9 | ||
|
|
bdee533f04 | ||
|
|
465f1e2328 | ||
|
|
3b672339ef | ||
|
|
33f4a2b1b1 | ||
|
|
0879d828a7 | ||
|
|
1726f3bd3b | ||
|
|
18ec4f2b87 | ||
|
|
93a5a7af7b | ||
|
|
25421aed06 | ||
|
|
c25bc27049 | ||
|
|
58e92cbb36 | ||
|
|
8af09f38e0 | ||
|
|
e2856c1c7e | ||
|
|
83cf08dfa0 | ||
|
|
0e2047f080 | ||
|
|
1cbd76f718 | ||
|
|
fe2ad5da66 | ||
|
|
f3881747be | ||
|
|
2daee785d4 | ||
|
|
064136634c | ||
|
|
b040fb1c8a | ||
|
|
4e9bff5b57 | ||
|
|
017a03c86b | ||
|
|
bad31e01b9 | ||
|
|
17d49c9d64 | ||
|
|
0ba17ebe5d | ||
|
|
1bfeb4b322 | ||
|
|
09c182c75a | ||
|
|
db7b863fa4 | ||
|
|
92324f8cbd | ||
|
|
eac34c4210 | ||
|
|
5de3f44cc7 | ||
|
|
20c65fa4ec | ||
|
|
30d6e75af1 | ||
|
|
d94f83d1bf | ||
|
|
0a726a99ac | ||
|
|
a600787c67 | ||
|
|
b935dd5b1d | ||
|
|
25da9eb467 | ||
|
|
eadd074122 | ||
|
|
8b29912521 | ||
|
|
3e17c7b30b | ||
|
|
40c097ff8a | ||
|
|
1eceb143ed | ||
|
|
f689a70b7e | ||
|
|
88e5d0aba7 | ||
|
|
8d6014683f | ||
|
|
9c28bd419d | ||
|
|
1bf1cdc190 | ||
|
|
86a9264a25 | ||
|
|
f204528cf4 | ||
|
|
b21febe3e1 | ||
|
|
a118df6060 | ||
|
|
5db52b1717 | ||
|
|
e6ac495dfb | ||
|
|
34f9da85dd | ||
|
|
d334d39e3f | ||
|
|
07c6172576 | ||
|
|
4d6f8d68a3 | ||
|
|
4c2fd11de2 | ||
|
|
8b3cdb2ebe | ||
|
|
2c233eac63 | ||
|
|
2f4174b560 | ||
|
|
ccf49b1105 | ||
|
|
a165595116 | ||
|
|
cdbaa41364 | ||
|
|
cc8ccb35bf | ||
|
|
92cd7ca970 | ||
|
|
13530fa1ef | ||
|
|
f9c8259050 | ||
|
|
d30a7b2318 | ||
|
|
652ab98e1a | ||
|
|
17d5413bc2 | ||
|
|
c1281a47ea | ||
|
|
32c15c3fe3 | ||
|
|
1b9810cfd9 | ||
|
|
781187a6d3 | ||
|
|
2cf44838bf | ||
|
|
6f60c4696f | ||
|
|
f89feeb197 | ||
|
|
e5ee2e8127 | ||
|
|
89baa34b8d | ||
|
|
ecad4000f2 | ||
|
|
1f42b720d0 | ||
|
|
bb773a05d5 | ||
|
|
7586e5e517 | ||
|
|
e5464739c9 | ||
|
|
0e29b73703 | ||
|
|
6723112498 | ||
|
|
cacf5f209d | ||
|
|
dc97ffb40e | ||
|
|
133baf8fc0 | ||
|
|
7212a66761 | ||
|
|
c690c0c447 | ||
|
|
74cf8a3943 | ||
|
|
49d330f2a8 | ||
|
|
3e3b5c0e89 | ||
|
|
6047d1079b | ||
|
|
c834aa67d4 | ||
|
|
24d3822f82 | ||
|
|
3579fd95a1 | ||
|
|
a6f4f1dc2e | ||
|
|
85540f1359 | ||
|
|
17f5f3d6cf | ||
|
|
be30db19f3 | ||
|
|
5f9125b044 | ||
|
|
84eba5982a | ||
|
|
cc0eebaa2f | ||
|
|
acc96d0726 | ||
|
|
6d3717d9c7 | ||
|
|
56a1588f96 | ||
|
|
aa7d243558 | ||
|
|
dcb6b5e117 | ||
|
|
067bbaf136 | ||
|
|
02724e7427 | ||
|
|
9f7cd8358f | ||
|
|
a06eab4ae1 | ||
|
|
0f54cfef92 | ||
|
|
fa69bf1da3 | ||
|
|
e7e1e67fc7 | ||
|
|
fae6f15fbe | ||
|
|
ebdd4d59b4 | ||
|
|
6f8ab2d9ec | ||
|
|
4363971e05 | ||
|
|
2cddcb14f6 | ||
|
|
ed89f965bf | ||
|
|
07750a74ba | ||
|
|
5955087887 | ||
|
|
61d054216d | ||
|
|
780f556e9c | ||
|
|
3f1e411f95 | ||
|
|
7e5fd9e655 | ||
|
|
8f4062f4da | ||
|
|
2624a47e88 | ||
|
|
56461e0173 | ||
|
|
4bbf33e119 | ||
|
|
e928445c91 | ||
|
|
94f9604493 | ||
|
|
a221be1818 | ||
|
|
b9b523d293 | ||
|
|
0003dd9c8c | ||
|
|
63c3e67c07 | ||
|
|
6df412401c | ||
|
|
284b13c137 | ||
|
|
c946e2d263 | ||
|
|
8608700ba9 | ||
|
|
6994edf40b | ||
|
|
f60a419e84 | ||
|
|
280869f883 | ||
|
|
9c58dcd145 | ||
|
|
a9c944483b | ||
|
|
61caf1c5eb | ||
|
|
0c2b510130 | ||
|
|
01b41130e5 | ||
|
|
fb763397b4 | ||
|
|
a7ed289c04 | ||
|
|
927b3dfe54 | ||
|
|
0000eed295 | ||
|
|
49df562431 | ||
|
|
d544247a53 | ||
|
|
04cb6cc6ff | ||
|
|
4d35e1845b | ||
|
|
c463d1d203 | ||
|
|
1aac7c1a4c | ||
|
|
8031d30ad2 | ||
|
|
ad771dfe3b | ||
|
|
00cd284e54 | ||
|
|
a925c32ecb | ||
|
|
be1fc5ce77 | ||
|
|
6accd9056f | ||
|
|
1cd908092b | ||
|
|
9d9f3b7afb | ||
|
|
8ca6049b32 | ||
|
|
fcdc42ea40 | ||
|
|
56c5212374 | ||
|
|
13bb8928c9 | ||
|
|
0bece3c17a | ||
|
|
9924b85773 | ||
|
|
8b50f8d07c | ||
|
|
9a53289a23 | ||
|
|
6e71870648 | ||
|
|
d7544e6192 | ||
|
|
d9a8ed29e8 | ||
|
|
9f86b661cb | ||
|
|
33cc594e39 | ||
|
|
35f1987b14 | ||
|
|
ff7a427189 | ||
|
|
7b90358c1e | ||
|
|
ef347b3a28 | ||
|
|
0c908cf913 | ||
|
|
1688d250dc | ||
|
|
8f4b665fb3 | ||
|
|
addfe66863 | ||
|
|
9353496864 | ||
|
|
936c1a4fa0 | ||
|
|
8e4e24a9b9 | ||
|
|
31f89d1813 | ||
|
|
dbb9b7014f | ||
|
|
e48a29a3f1 | ||
|
|
1f16691715 | ||
|
|
baf1d4a604 | ||
|
|
968fd0ca40 | ||
|
|
852567122e | ||
|
|
eefbd2ef87 | ||
|
|
11d2901fc7 | ||
|
|
0864b3a5ba | ||
|
|
05ac4be397 | ||
|
|
f8ca312cfa | ||
|
|
292ed31c4d | ||
|
|
5de4e5e9e9 | ||
|
|
fc0c2fe6da | ||
|
|
45f0a5d543 | ||
|
|
e97d70d152 | ||
|
|
d0bd3cc033 | ||
|
|
803c6baaea | ||
|
|
2f621b80d5 | ||
|
|
7773f82726 |
116
README.md
116
README.md
@@ -1,29 +1,109 @@
|
||||
# IPFire 2.x - The Open Source Firewall
|
||||
# BPFire - eBPF Network Firewall OS (eBPF 网络防火墙)
|
||||
|
||||
# What is IPFire?
|
||||
# What is BPFire?
|
||||
|
||||
IPFire is a hardened, versatile, state-of-the-art Open Source firewall based on
|
||||
Linux. Its ease of use, high performance in any scenario and extensibility make
|
||||
it usable for everyone. For a full list of features have a look [here](https://www.ipfire.org/features).
|
||||
BPFire is fork of [IPFire 2.x](https://github.com/ipfire/ipfire-2.x), a hardened, versatile, state-of-the-art Open Source firewall based on Linux. BPFire is to enable revolutionary [eBPF](https://ebpf.io/) technology for non-tech savvy users, make eBPF technology consumable to home users or any size of organizations to secure their network environment. Current supported eBPF network application features:
|
||||
|
||||
This repository contains the source code of IPFire 2.x which is used to build
|
||||
the whole distribution from scratch, since IPFire is not based on any other
|
||||
distribution.
|
||||
BPFire 基于IPFire 2.x, 一个基于Linux的安全坚固、多功能、先进的开源防火墙. BPFire 为普罗大众带来革命创新性的eBPF技术,为家庭用户或任何大小组织企业的网络安全保驾护航. 当前支持的eBPF应用包括:
|
||||
|
||||
# Where can I get IPFire?
|
||||
1. XDP DDoS protection, See XDP SYNPROXY stops 10G DDoS SYN flood [here](https://www.youtube.com/watch?v=81Hgoy-x1A4)
|
||||
2. XDP UDP DDoS online game protection
|
||||
3. XDP DNS domain blocklist, ratelimit protection
|
||||
4. XDP SSL/TLS server name indicator (SNI) blocklist
|
||||
5. XDP GeoIP/Country blocklist
|
||||
6. XDP multi attachment and capture mode for Intrusion Detection System Suricata in IPS mode
|
||||
7. eBPF based LoxiLB load balancer, Firewall, Proxy, see full features [LoxiLB](https://loxilb-io.github.io/loxilbdocs/#overall-features-of-loxilb)
|
||||
|
||||
Just head over to https://www.ipfire.org/download
|
||||
# Where can I get support?
|
||||
|
||||
# How do I use this software?
|
||||
Open github issue or [discord](https://discord.gg/EakRJaU8NG)
|
||||
|
||||
We have a long and detailed wiki located [here](https://wiki.ipfire.org/) which
|
||||
should answers most of your questions.
|
||||
# Where can I get BPFire installation ISO or LoongFire flash image?
|
||||
|
||||
# But I have some questions left. Where can I get support?
|
||||
中国大陆用户下载地址:
|
||||
|
||||
You can ask your question at our community located [here](https://community.ipfire.org/).
|
||||
A complete list of our support channels can be found [here](https://www.ipfire.org/support).
|
||||
[bpfire](https://www.vcn.bc.ca/~vli/bpfire/)
|
||||
|
||||
# How can I contribute?
|
||||
[loongfire](https://www.vcn.bc.ca/~vli/loongfire/)
|
||||
|
||||
We have another document for this. Please look [here](doc/CONTRIBUTING.md).
|
||||
Other download site:
|
||||
|
||||
[bpfire.net](https://bpfire.net/download/)
|
||||
|
||||
# What computer hardwares BPFire support?
|
||||
|
||||
BPFire support commodity computer hardware, small or large, old or new, cheap or expensive.
|
||||
|
||||
for example:
|
||||
|
||||
[X86 mini PC](https://www.aliexpress.com/w/wholesale-home-firewall-router.html?spm=a2g0o.best.search.0)
|
||||
|
||||
[LoongArch mini PC](https://www.aliexpress.us/item/3256807861547435.html?spm=a2g0o.order_list.order_list_main.5.6c6c1802f4v4tf&gatewayAdapt=glo2usa)
|
||||
|
||||
# How do I install BPFire?
|
||||
|
||||
flash the ISO to USB on Linux machine, /dev/sdc is your USB thrumb drive.
|
||||
|
||||
`dd if=bpfire-2.29-core184-x86_64.iso of=/dev/sdc status=progress`
|
||||
|
||||
BPFire installation on mini industrial PC:
|
||||
|
||||
[](https://www.youtube.com/watch?v=p9iHCe0hXPs "BPFire installation on mini industrial PC")
|
||||
|
||||
# BPFire SYNPROXY throughput with and without XDP acceleration under 10Gbit DDoS SYN flood:
|
||||
|
||||
[](https://www.youtube.com/watch?v=81Hgoy-x1A4 "Throughput performance")
|
||||
|
||||
|
||||
# BPFire WebUI screenshot:
|
||||
|
||||
English:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Chinese:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
# Does BPFire run in hypervisor virtual environment?
|
||||
|
||||
Yes, We have tested in Linux KVM hypervisor, Proxmox, Microsoft Hyper-v, should support Virtualbox, VMware as well.
|
||||
|
||||
Microsoft Hyper-v screen shot:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
# How to build BPFire?
|
||||
|
||||
Build Environment Setup https://www.ipfire.org/docs/devel/ipfire-2-x/build-initial
|
||||
|
||||
(It takes a few hours to build image for first build depending on build machine power)
|
||||
|
||||
for example on Ubuntu 22.04 LTS:
|
||||
|
||||
```
|
||||
apt install git-core g++ manpages-pl patch byacc make autoconf automake libltdl-dev
|
||||
|
||||
git clone https://github.com/vincentmli/bpfire.git
|
||||
|
||||
cd bpfire
|
||||
|
||||
wget --mirror --convert-links --adjust-extension --page-requisites --no-parent --cut-dirs=2 -nH --reject "index.html*" --reject "*.gif" https://www.bpfire.net/download/bpfire/cache/
|
||||
|
||||
./make.sh build
|
||||
|
||||
```
|
||||
|
||||
# How do I support BPFire development?
|
||||
|
||||
Join or [Donate to BPFire paypal](https://www.paypal.com/donate/?business=BL97G8687E5B6&no_recurring=0&item_name=Make+revolutionary+eBPF+technology+available+for+non-tech+savvy+users+for+safe+online+surfing¤cy_code=USD)
|
||||
|
||||
9
config/cfgroot/ddos-settings
Normal file
9
config/cfgroot/ddos-settings
Normal file
@@ -0,0 +1,9 @@
|
||||
22=off
|
||||
ENABLE_DDOS=off
|
||||
25=off
|
||||
80=off
|
||||
53=off
|
||||
8080=off
|
||||
8090=off
|
||||
443=off
|
||||
5555=off
|
||||
1
config/cfgroot/dns-ddos-settings
Normal file
1
config/cfgroot/dns-ddos-settings
Normal file
@@ -0,0 +1 @@
|
||||
ENABLE_DNS_DDOS=off
|
||||
@@ -26,6 +26,7 @@ $General::swroot = 'CONFIG_ROOT';
|
||||
$General::noipprefix = 'noipg-';
|
||||
|
||||
require "${General::swroot}/network-functions.pl";
|
||||
require "${General::swroot}/wireguard-functions.pl";
|
||||
|
||||
# This function executes a shell command without forking a shell or do any other
|
||||
# Perl-voodoo before it. It deprecates the "system" command and is the only way
|
||||
@@ -180,7 +181,26 @@ sub setup_default_networks
|
||||
$defaultNetworks->{'IPsec RW (' .$ip."/".$sub.")"}{'NET'} = &getnextip($ip);
|
||||
}
|
||||
}
|
||||
|
||||
# WireGuard
|
||||
if ($Wireguard::settings{'CLIENT_POOL'}) {
|
||||
my $name = $Lang::tr{'wg rw peers'};
|
||||
|
||||
$defaultNetworks->{$name}{'NAME'} = "WGRW";
|
||||
}
|
||||
}
|
||||
|
||||
sub set_defaults($$) {
|
||||
my $hash = shift;
|
||||
my $defaults = shift;
|
||||
|
||||
foreach my $key (keys %$defaults) {
|
||||
unless (defined($hash->{$key})) {
|
||||
$hash->{$key} = $defaults->{$key};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub get_aliases
|
||||
{
|
||||
|
||||
@@ -366,6 +386,14 @@ sub validip
|
||||
}
|
||||
}
|
||||
|
||||
sub validnum {
|
||||
my $num = shift;
|
||||
if ($num =~ /^\d+$/) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub validmask {
|
||||
my $mask = shift;
|
||||
|
||||
@@ -842,6 +870,14 @@ sub validportrange # used to check a port range
|
||||
}
|
||||
}
|
||||
|
||||
# Checks for a valid country code
|
||||
sub validcc($) {
|
||||
my $cc = shift;
|
||||
|
||||
# Must contain of exactly two uppercase characters, or must be A1, A2, or A3
|
||||
return ($cc =~ m/^([A-Z]{2}|A[123])$/);
|
||||
}
|
||||
|
||||
sub IpInSubnet {
|
||||
my $addr = shift;
|
||||
my $network = shift;
|
||||
@@ -1306,6 +1342,22 @@ sub grab_address_from_file($) {
|
||||
return;
|
||||
}
|
||||
|
||||
sub get_ipaddresses_from_interface($) {
|
||||
my ($interface) = @_;
|
||||
my @ip_addresses;
|
||||
|
||||
my $output = `ip addr show $interface 2>/dev/null`;
|
||||
|
||||
# Check if the command was successful
|
||||
if ($? == 0) {
|
||||
# Extract IP addresses using regex
|
||||
while ($output =~ /inet (\d+\.\d+\.\d+\.\d+)/g) {
|
||||
push @ip_addresses, $1;
|
||||
}
|
||||
}
|
||||
return @ip_addresses;
|
||||
}
|
||||
|
||||
# Function to get all configured and enabled nameservers.
|
||||
sub get_nameservers () {
|
||||
my %settings;
|
||||
|
||||
1
config/cfgroot/haproxy-settings
Normal file
1
config/cfgroot/haproxy-settings
Normal file
@@ -0,0 +1 @@
|
||||
ENABLE_HAPROXY=off
|
||||
@@ -16,6 +16,7 @@ use File::Basename;
|
||||
use HTML::Entities();
|
||||
use Socket;
|
||||
use Time::Local;
|
||||
use Unicode::Normalize;
|
||||
|
||||
our %color = ();
|
||||
&General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", \%color);
|
||||
@@ -35,6 +36,7 @@ $Header::colouryellow = '#FFFF00';
|
||||
$Header::colourgreen = '#339933';
|
||||
$Header::colourblue = '#333399';
|
||||
$Header::colourovpn = '#339999';
|
||||
$Header::colourwg = '#ff007f';
|
||||
$Header::colourfw = '#000000';
|
||||
$Header::colourvpn = '#990099';
|
||||
$Header::colourerr = '#FF0000';
|
||||
@@ -362,6 +364,18 @@ sub escape($) {
|
||||
return HTML::Entities::encode_entities($s);
|
||||
}
|
||||
|
||||
sub normalize($) {
|
||||
my $s = shift;
|
||||
|
||||
# Remove any special characters
|
||||
$s = &Unicode::Normalize::NFKD($s);
|
||||
|
||||
# Remove any whitespace and replace with dash
|
||||
$s =~ s/\s+/\-/g;
|
||||
|
||||
return $s;
|
||||
}
|
||||
|
||||
sub cleanhtml {
|
||||
my $outstring =$_[0];
|
||||
$outstring =~ tr/,/ / if not defined $_[1] or $_[1] ne 'y';
|
||||
|
||||
1
config/cfgroot/loxilb-FWconfig.txt
Normal file
1
config/cfgroot/loxilb-FWconfig.txt
Normal file
@@ -0,0 +1 @@
|
||||
{"fwAttr":[{"opts":{"counter":"0:0","doSnat":true,"onDefault":true,"toIP":"REDIP"},"ruleArguments":{"destinationIP":"0.0.0.0/0","portName":"green0","sourceIP":"0.0.0.0/0"}}]}
|
||||
1
config/cfgroot/loxilb-settings
Normal file
1
config/cfgroot/loxilb-settings
Normal file
@@ -0,0 +1 @@
|
||||
ENABLE_LOXILB=off
|
||||
@@ -48,6 +48,7 @@ wakeonlan.cgi=configuration/network/wake-on-lan
|
||||
|
||||
# Services menu
|
||||
vpnmain.cgi=configuration/services/ipsec
|
||||
wireguard.cgi=configuration/services/wireguard
|
||||
ovpnmain.cgi=configuration/services/openvpn
|
||||
ddns.cgi=configuration/services/dyndns
|
||||
time.cgi=configuration/services/ntp
|
||||
|
||||
@@ -291,6 +291,55 @@ sub get_broadcast($) {
|
||||
return &bin2ip($network_bin ^ ~$netmask_bin);
|
||||
}
|
||||
|
||||
sub get_prefix($) {
|
||||
my $network = shift;
|
||||
|
||||
# Convert to binary
|
||||
my ($network_bin, $netmask_bin) = &network2bin($network);
|
||||
|
||||
if (defined $netmask_bin) {
|
||||
my $prefix = 0;
|
||||
|
||||
while (1) {
|
||||
# End the loop if we have consumed all ones
|
||||
last if ($netmask_bin == 0);
|
||||
|
||||
# Increment prefix
|
||||
$prefix++;
|
||||
|
||||
# Remove the most-significant one
|
||||
$netmask_bin <<= 1;
|
||||
$netmask_bin &= 0xffffffff;
|
||||
}
|
||||
|
||||
return $prefix;
|
||||
}
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub get_netmask($) {
|
||||
my $network = shift;
|
||||
|
||||
# Fetch the prefix
|
||||
my $prefix = &get_prefix($network);
|
||||
|
||||
# Convert to netmask
|
||||
return &convert_prefix2netmask($prefix);
|
||||
}
|
||||
|
||||
sub normalize_network($) {
|
||||
my $network = shift;
|
||||
my $address = &get_netaddress($network);
|
||||
my $prefix = &get_prefix($network);
|
||||
|
||||
unless (defined $address && defined $prefix) {
|
||||
return undef;
|
||||
}
|
||||
|
||||
return "${address}/${prefix}";
|
||||
}
|
||||
|
||||
# Returns True if $address is in $network.
|
||||
sub ip_address_in_network($$) {
|
||||
my $address = shift;
|
||||
|
||||
8
config/cfgroot/tcp_ports
Normal file
8
config/cfgroot/tcp_ports
Normal file
@@ -0,0 +1,8 @@
|
||||
ssh 22/tcp # The Secure Shell (SSH) Protocol
|
||||
smtp 25/tcp # Simple Mail Transfer
|
||||
http 80/tcp # World Wide Web HTTP
|
||||
https 443/tcp # http protocol over TLS/SSL
|
||||
domain 53/tcp # Domain Name Server
|
||||
httpalt 8080/tcp # HTTP Alternate (see port 80)
|
||||
opsmessaging 8090/tcp # Vehicle to station messaging
|
||||
userdefined 5555/tcp # Vehicle to station messaging
|
||||
5
config/cfgroot/udp-ddos-settings
Normal file
5
config/cfgroot/udp-ddos-settings
Normal file
@@ -0,0 +1,5 @@
|
||||
53=off
|
||||
ENABLE_UDP_DDOS=off
|
||||
5060=off
|
||||
5061=off
|
||||
10408=off
|
||||
5
config/cfgroot/udp_ports
Normal file
5
config/cfgroot/udp_ports
Normal file
@@ -0,0 +1,5 @@
|
||||
domain 53/udp # Domain Name Server
|
||||
game1 10408/udp # Domain Name Server
|
||||
sip 5060/udp # Voice over Internet
|
||||
siptls 5061/udp # Voice over Internet TLS
|
||||
|
||||
675
config/cfgroot/wireguard-functions.pl
Normal file
675
config/cfgroot/wireguard-functions.pl
Normal file
@@ -0,0 +1,675 @@
|
||||
#!/usr/bin/perl
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2024 Michael Tremer <michael.tremer@ipfire.org> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
package Wireguard;
|
||||
|
||||
use strict;
|
||||
use MIME::Base64;
|
||||
|
||||
require "/var/ipfire/general-functions.pl";
|
||||
require "/var/ipfire/network-functions.pl";
|
||||
|
||||
our @DEFAULT_PORTRANGE = (60000, 62000);
|
||||
our $DEFAULT_PORT = 51820;
|
||||
our $DEFAULT_KEEPALIVE = 25;
|
||||
|
||||
# Read the global configuration
|
||||
our %settings = ();
|
||||
|
||||
if (-e "/var/ipfire/wireguard/settings") {
|
||||
&General::readhash("/var/ipfire/wireguard/settings", \%settings);
|
||||
}
|
||||
|
||||
# Read all peers
|
||||
our %peers = ();
|
||||
|
||||
if (-e "/var/ipfire/wireguard/peers") {
|
||||
&General::readhasharray("/var/ipfire/wireguard/peers", \%peers);
|
||||
}
|
||||
|
||||
# Set any defaults
|
||||
&General::set_defaults(\%settings, {
|
||||
"ENABLED" => "off",
|
||||
"PORT" => $DEFAULT_PORT,
|
||||
"CLIENT_DNS" => $Network::ethernet{'GREEN_ADDRESS'},
|
||||
});
|
||||
|
||||
# Returns true if WireGuard is enabled
|
||||
sub is_enabled() {
|
||||
return ($settings{'ENABLED'} eq "on");
|
||||
}
|
||||
|
||||
# Returns the local endpoint
|
||||
sub get_endpoint() {
|
||||
my $endpoint = $settings{'ENDPOINT'};
|
||||
|
||||
# If no endpoint is set, we fall back to the FQDN of the firewall
|
||||
if ($endpoint eq "") {
|
||||
$endpoint = $General::mainsettings{'HOSTNAME'} . "." . $General::mainsettings{'DOMAINNAME'};
|
||||
}
|
||||
|
||||
return $endpoint;
|
||||
}
|
||||
|
||||
# This function generates a set of keys for this host if none exist
|
||||
sub generate_keys($) {
|
||||
my $force = shift || 0;
|
||||
|
||||
# Reset any previous keys if re-generation forced
|
||||
if ($force) {
|
||||
$settings{"PRIVATE_KEY"} = undef;
|
||||
$settings{"PUBLIC_KEY"} = undef;
|
||||
}
|
||||
|
||||
# Return if we already have keys
|
||||
return if (defined $settings{"PRIVATE_KEY"} && defined $settings{"PUBLIC_KEY"});
|
||||
|
||||
# Generate a new private key
|
||||
unless (defined $settings{'PRIVATE_KEY'}) {
|
||||
# Generate a new private key
|
||||
$settings{"PRIVATE_KEY"} = &generate_private_key();
|
||||
|
||||
# Reset the public key
|
||||
$settings{"PUBLIC_KEY"} = undef;
|
||||
}
|
||||
|
||||
# Derive the public key
|
||||
unless (defined $settings{"PUBLIC_KEY"}) {
|
||||
# Derive the public key
|
||||
$settings{"PUBLIC_KEY"} = &derive_public_key($settings{"PRIVATE_KEY"});
|
||||
}
|
||||
|
||||
# Store the configuration file
|
||||
&General::writehash("/var/ipfire/wireguard/settings", \%settings);
|
||||
}
|
||||
|
||||
# Generates a new private key
|
||||
sub generate_private_key() {
|
||||
# Generate a new private key
|
||||
my @output = &General::system_output("wg", "genkey");
|
||||
|
||||
# Store the key
|
||||
foreach (@output) {
|
||||
chomp;
|
||||
|
||||
return $_;
|
||||
}
|
||||
|
||||
# Return undefined on error
|
||||
return undef;
|
||||
}
|
||||
|
||||
# Takes a private key and derives the public key
|
||||
sub derive_public_key($) {
|
||||
my $private_key = shift;
|
||||
my @output = ();
|
||||
|
||||
# Derive the public key
|
||||
if (open(STDIN, "-|")) {
|
||||
@output = &General::system_output("wg", "pubkey");
|
||||
} else {
|
||||
print $private_key . "\n";
|
||||
exit (0);
|
||||
}
|
||||
|
||||
# Return the first line
|
||||
foreach (@output) {
|
||||
chomp;
|
||||
|
||||
return $_;
|
||||
}
|
||||
|
||||
# Return undefined on error
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub dump($) {
|
||||
my $intf = shift;
|
||||
|
||||
my %dump = ();
|
||||
my $lineno = 0;
|
||||
|
||||
# Fetch the dump
|
||||
my @output = &General::system_output("/usr/local/bin/wireguardctrl", "dump", $intf);
|
||||
|
||||
foreach my $line (@output) {
|
||||
# Increment the line numbers
|
||||
$lineno++;
|
||||
|
||||
# Skip the first line
|
||||
next if ($lineno <= 1);
|
||||
|
||||
# Split the line into its fields
|
||||
my @fields = split(/\t/, $line);
|
||||
|
||||
# Create a new hash indexed by the public key
|
||||
$dump{$fields[0]} = {
|
||||
"psk" => $fields[1],
|
||||
"endpoint" => $fields[2],
|
||||
"allowed-ips" => $fields[3],
|
||||
"latest-handshake" => $fields[4],
|
||||
"transfer-rx" => $fields[5],
|
||||
"transfer-tx" => $fields[6],
|
||||
"persistent-keepalive" => $fields[7],
|
||||
};
|
||||
}
|
||||
|
||||
return %dump;
|
||||
}
|
||||
|
||||
sub load_peer($) {
|
||||
my $key = shift;
|
||||
|
||||
my $type = $peers{$key}[1];
|
||||
|
||||
my %peer = (
|
||||
"ENABLED" => $peers{$key}[0],
|
||||
"TYPE" => $type,
|
||||
"NAME" => $peers{$key}[2],
|
||||
"PUBLIC_KEY" => $peers{$key}[3],
|
||||
"PRIVATE_KEY" => $peers{$key}[4],
|
||||
"PORT" => $peers{$key}[5],
|
||||
"ENDPOINT_ADDR" => $peers{$key}[6],
|
||||
"ENDPOINT_PORT" => $peers{$key}[7],
|
||||
($type eq "host") ? "CLIENT_ADDRESS" : "REMOTE_SUBNETS"
|
||||
=> &decode_subnets($peers{$key}[8]),
|
||||
"REMARKS" => &decode_remarks($peers{$key}[9]),
|
||||
"LOCAL_SUBNETS" => &decode_subnets($peers{$key}[10]),
|
||||
"PSK" => $peers{$key}[11],
|
||||
"KEEPALIVE" => $peers{$key}[12],
|
||||
"LOCAL_ADDRESS" => $peers{$key}[13],
|
||||
"INTERFACE" => ($type eq "host") ? "wg0" : "wg${key}",
|
||||
);
|
||||
|
||||
return \%peer;
|
||||
}
|
||||
|
||||
sub get_peer_by_name($) {
|
||||
my $name = shift;
|
||||
|
||||
foreach my $key (keys %peers) {
|
||||
my $peer = &load_peer($key);
|
||||
|
||||
# Return the peer if the name matches
|
||||
if ($peer->{"NAME"} eq $name) {
|
||||
return $peer;
|
||||
}
|
||||
}
|
||||
|
||||
# Return undefined if nothing was found
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub name_is_valid($) {
|
||||
my $name = shift;
|
||||
|
||||
# The name must be between 1 and 63 characters
|
||||
if (length ($name) < 1 || length ($name) > 63) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Only valid characters are a-z, A-Z, 0-9, space and -
|
||||
if ($name !~ /^[a-zA-Z0-9 -]*$/) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub name_is_free($) {
|
||||
my $name = shift;
|
||||
my $key = shift || 0;
|
||||
|
||||
foreach my $i (keys %peers) {
|
||||
# Skip the connection with ID
|
||||
next if ($key eq $i);
|
||||
|
||||
# Return if we found a match
|
||||
return 0 if ($peers{$i}[2] eq $name);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub key_is_valid($) {
|
||||
my $key = shift;
|
||||
|
||||
# Try to decode the key
|
||||
$key = &MIME::Base64::decode_base64($key);
|
||||
|
||||
# All keys must be 32 bytes long
|
||||
return length($key) == 32;
|
||||
}
|
||||
|
||||
sub keepalive_is_valid($) {
|
||||
my $keepalive = shift;
|
||||
|
||||
# Must be a number
|
||||
return 0 unless ($keepalive =~ m/^[0-9]+$/);
|
||||
|
||||
# Must be between 0 and 65535 (inclusive)
|
||||
return 0 if ($keepalive lt 0);
|
||||
return 0 if ($keepalive gt 65535);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub encode_remarks($) {
|
||||
my $remarks = shift;
|
||||
|
||||
# Encode to Base64
|
||||
$remarks = &MIME::Base64::encode_base64($remarks);
|
||||
|
||||
# Remove the trailing newline
|
||||
chomp($remarks);
|
||||
|
||||
return $remarks;
|
||||
}
|
||||
|
||||
sub decode_remarks($) {
|
||||
my $remarks = shift;
|
||||
|
||||
# Decode from base64
|
||||
return &MIME::Base64::decode_base64($remarks);
|
||||
}
|
||||
|
||||
sub encode_subnets($) {
|
||||
my @subnets = @_;
|
||||
|
||||
my @formatted = ();
|
||||
|
||||
# wg only handles the CIDR notation
|
||||
foreach my $subnet (@subnets) {
|
||||
my $netaddr = &Network::get_netaddress($subnet);
|
||||
my $prefix = &Network::get_prefix($subnet);
|
||||
|
||||
next unless (defined $netaddr && defined $prefix);
|
||||
|
||||
push(@formatted, "${netaddr}/${prefix}");
|
||||
}
|
||||
|
||||
# Join subnets together separated by |
|
||||
return join("|", @formatted);
|
||||
}
|
||||
|
||||
sub decode_subnets($) {
|
||||
my $subnets = shift;
|
||||
|
||||
# Split the string
|
||||
my @subnets = split(/\|/, $subnets);
|
||||
|
||||
return \@subnets;
|
||||
}
|
||||
|
||||
sub pool_is_in_use($) {
|
||||
my $pool = shift;
|
||||
|
||||
foreach my $key (keys %peers) {
|
||||
my $type = $peers{$key}[1];
|
||||
my $address = $peers{$key}[6];
|
||||
|
||||
# Check if a host is using an IP address from the pool
|
||||
if ($type eq "host" && &Network::ip_address_in_network($address, $pool)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
# No match found
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Takes the pool and an optional limit of up to how many addresses to return
|
||||
sub free_pool_addresses($$) {
|
||||
my $pool = shift;
|
||||
my $limit = shift || 0;
|
||||
|
||||
my @used_addresses = ();
|
||||
my @free_addresses = ();
|
||||
|
||||
# wg0 IP is reserved so put in @used_addresses
|
||||
push(@used_addresses, &Network::ip2bin($settings{'ADDRESS'}));
|
||||
|
||||
# Collect all used addresses
|
||||
foreach my $key (keys %peers) {
|
||||
my $peer = &load_peer($key);
|
||||
|
||||
# Only check hosts
|
||||
next if ($peer->{"TYPE"} ne "host");
|
||||
|
||||
foreach my $address (@{ $peer->{"CLIENT_ADDRESS"} }) {
|
||||
push(@used_addresses, &Network::ip2bin($address));
|
||||
}
|
||||
}
|
||||
|
||||
# Fetch the first address
|
||||
my $address = &Network::get_netaddress($pool);
|
||||
|
||||
# Fetch the last address
|
||||
my $broadcast = &Network::get_broadcast($pool);
|
||||
$broadcast = &Network::ip2bin($broadcast);
|
||||
|
||||
# Walk through all addresses excluding the first and last address.
|
||||
# No technical reason, we just don't want to confuse people.
|
||||
OUTER: for (my $i = &Network::ip2bin($address) + 1; $i < $broadcast; $i++) {
|
||||
# Skip any addresses that already in use
|
||||
foreach my $used_address (@used_addresses) {
|
||||
next OUTER if ($i == $used_address);
|
||||
}
|
||||
|
||||
push(@free_addresses, &Network::bin2ip($i));
|
||||
|
||||
# Check limit
|
||||
last if ($limit > 0 && scalar @free_addresses >= $limit);
|
||||
}
|
||||
|
||||
return @free_addresses;
|
||||
}
|
||||
|
||||
sub generate_peer_configuration($$) {
|
||||
my $key = shift;
|
||||
my $private_key = shift;
|
||||
|
||||
my @conf = ();
|
||||
|
||||
# Load the peer
|
||||
my $peer = &load_peer($key);
|
||||
|
||||
# Return if we could not find the peer
|
||||
return undef unless ($peer);
|
||||
|
||||
my @allowed_ips = ();
|
||||
|
||||
# Convert all subnets into CIDR notation
|
||||
foreach my $subnet (@{ $peer->{'LOCAL_SUBNETS'} }) {
|
||||
my $netaddress = &Network::get_netaddress($subnet);
|
||||
my $prefix = &Network::get_prefix($subnet);
|
||||
|
||||
# Skip invalid subnets
|
||||
next if (!defined $netaddress || !defined $prefix);
|
||||
|
||||
push(@allowed_ips, "${netaddress}/${prefix}");
|
||||
}
|
||||
|
||||
# Fetch the endpoint
|
||||
my $endpoint = &get_endpoint();
|
||||
|
||||
# Net-2-Net
|
||||
if ($peer->{'TYPE'} eq "net") {
|
||||
# Derive our own public key
|
||||
my $public_key = &derive_public_key($peer->{'PRIVATE_KEY'});
|
||||
|
||||
push(@conf,
|
||||
"[Interface]",
|
||||
"PrivateKey = $private_key",
|
||||
"ListenPort = $peer->{'ENDPOINT_PORT'}",
|
||||
"",
|
||||
"[Peer]",
|
||||
"Endpoint = ${endpoint}:$peer->{'PORT'}",
|
||||
"PublicKey = $public_key",
|
||||
"PresharedKey = $peer->{'PSK'}",
|
||||
"AllowedIPs = " . join(", ", @allowed_ips),
|
||||
"PersistentKeepalive = $peer->{'KEEPALIVE'}",
|
||||
);
|
||||
|
||||
# Host-2-Net
|
||||
} elsif ($peer->{'TYPE'} eq "host") {
|
||||
# Fetch any DNS servers for hosts
|
||||
my @dns = split(/\|/, $settings{'CLIENT_DNS'});
|
||||
|
||||
push(@conf,
|
||||
"[Interface]",
|
||||
"PrivateKey = $private_key",
|
||||
"Address = @{ $peer->{'CLIENT_ADDRESS'} }/32",
|
||||
);
|
||||
|
||||
# Optionally add DNS servers
|
||||
if (scalar @dns) {
|
||||
push(@conf, "DNS = " . join(", ", @dns));
|
||||
}
|
||||
|
||||
# Finish the [Interface] section
|
||||
push(@conf, "");
|
||||
|
||||
# Add peer configuration
|
||||
push(@conf, (
|
||||
"[Peer]",
|
||||
"Endpoint = ${endpoint}:$settings{'PORT'}",
|
||||
"PublicKey = $settings{'PUBLIC_KEY'}",
|
||||
"PresharedKey = $peer->{'PSK'}",
|
||||
"AllowedIPs = " . join(", ", @allowed_ips),
|
||||
"PersistentKeepalive = $DEFAULT_KEEPALIVE",
|
||||
));
|
||||
}
|
||||
|
||||
return join("\n", @conf);
|
||||
}
|
||||
|
||||
sub parse_configuration($$) {
|
||||
my $name = shift;
|
||||
my $fh = shift;
|
||||
|
||||
my %peer = (
|
||||
"NAME" => $name,
|
||||
);
|
||||
|
||||
# Collect any errors
|
||||
my @errormessages = ();
|
||||
|
||||
my $section = undef;
|
||||
my $key = undef;
|
||||
my $val = undef;
|
||||
|
||||
# Check if the name is valid
|
||||
unless (&Wireguard::name_is_valid($name)) {
|
||||
push(@errormessages, $Lang::tr{'wg invalid name'});
|
||||
}
|
||||
|
||||
# Check if the name is already taken
|
||||
unless (&Wireguard::name_is_free($name)) {
|
||||
push(@errormessages, $Lang::tr{'wg name is already used'});
|
||||
}
|
||||
|
||||
while (<$fh>) {
|
||||
# Remove line breaks
|
||||
chomp;
|
||||
|
||||
# Remove any carriage returns
|
||||
$_ =~ s/\r$//;
|
||||
|
||||
# Search for section headers
|
||||
if ($_ =~ m/^\[(\w+)\]$/) {
|
||||
$section = $1;
|
||||
next;
|
||||
|
||||
# Search for key = value lines
|
||||
} elsif ($_ =~ m/^(\w+)\s+=\s+(.*)$/) {
|
||||
# Skip anything before the first section header
|
||||
next unless (defined $section);
|
||||
|
||||
# Store keys and values
|
||||
$key = $1;
|
||||
$val = $2;
|
||||
|
||||
# Skip any unhandled lines
|
||||
} else {
|
||||
next;
|
||||
}
|
||||
|
||||
# Interface section
|
||||
if ($section eq "Interface") {
|
||||
# Address
|
||||
if ($key eq "Address") {
|
||||
my $address = &Network::get_netaddress($val);
|
||||
my $prefix = &Network::get_prefix($val);
|
||||
|
||||
# There must be an address
|
||||
unless ($address) {
|
||||
push(@errormessages, $Lang::tr{'invalid ip address'});
|
||||
}
|
||||
|
||||
# If there was a prefix it must be /32
|
||||
if (defined $prefix) {
|
||||
unless ($prefix == 32) {
|
||||
push(@errormessages, $Lang::tr{'invalid ip address'});
|
||||
}
|
||||
}
|
||||
|
||||
# Store the address
|
||||
$peer{'LOCAL_ADDRESS'} = ${address};
|
||||
|
||||
# ListenPort
|
||||
} elsif ($key eq "ListenPort") {
|
||||
if (&General::validport($val)) {
|
||||
$peer{'PORT'} = $val;
|
||||
} else {
|
||||
push(@errormessages, $Lang::tr{'wg invalid endpoint port'});
|
||||
}
|
||||
|
||||
# PrivateKey
|
||||
} elsif ($key eq "PrivateKey") {
|
||||
if (&key_is_valid($val)) {
|
||||
$peer{'PRIVATE_KEY'} = $val;
|
||||
} else {
|
||||
push(@errormessages, $Lang::tr{'malformed private key'});
|
||||
}
|
||||
}
|
||||
|
||||
# Peer section
|
||||
} elsif ($section eq "Peer") {
|
||||
# PublicKey
|
||||
if ($key eq "PublicKey") {
|
||||
if (&key_is_valid($val)) {
|
||||
$peer{'PUBLIC_KEY'} = $val;
|
||||
} else {
|
||||
push(@errormessages, $Lang::tr{'malformed public key'});
|
||||
}
|
||||
|
||||
# PresharedKey
|
||||
} elsif ($key eq "PresharedKey") {
|
||||
if (&key_is_valid($val)) {
|
||||
$peer{'PSK'} = $val;
|
||||
} else {
|
||||
push(@errormessages, $Lang::tr{'malformed preshared key'});
|
||||
}
|
||||
|
||||
# AllowedIPs
|
||||
} elsif ($key eq "AllowedIPs") {
|
||||
my @networks = split(/,/, $val);
|
||||
|
||||
# Check if all networks are valid
|
||||
foreach my $network (@networks) {
|
||||
# Skip any IPv6 networks
|
||||
next if ($network =~ m/:/);
|
||||
|
||||
unless (&Network::check_subnet($network)) {
|
||||
push(@errormessages, $Lang::tr{'invalid network'} . " $network");
|
||||
}
|
||||
}
|
||||
|
||||
$peer{'REMOTE_SUBNETS'} = \@networks;
|
||||
# Endpoint
|
||||
} elsif ($key eq "Endpoint") {
|
||||
my $address = $val;
|
||||
my $port = $DEFAULT_PORT;
|
||||
|
||||
# Try to separate the port (if any)
|
||||
if ($val =~ m/^(.*):(\d+)$/) {
|
||||
$address = $1;
|
||||
$port = $2;
|
||||
}
|
||||
|
||||
# Check if we have a valid IP address
|
||||
if (&Network::check_ip_address($address)) {
|
||||
# nothing
|
||||
|
||||
# Check if we have a valid FQDN
|
||||
} elsif (&General::validfqdn($address)) {
|
||||
# nothing
|
||||
|
||||
# Otherwise this fails
|
||||
} else {
|
||||
push(@errormessages, $Lang::tr{'invalid endpoint address'});
|
||||
next;
|
||||
}
|
||||
|
||||
# Store the values
|
||||
$peer{'ENDPOINT_ADDRESS'} = $address;
|
||||
$peer{'ENDPOINT_PORT'} = $port;
|
||||
|
||||
# PersistentKeepalive
|
||||
} elsif ($key eq "PersistentKeepalive") {
|
||||
# Must be an integer
|
||||
if ($val =~ m/^(\d+)$/) {
|
||||
$peer{'KEEPALIVE'} = $1;
|
||||
} else {
|
||||
push(@errormessages, $Lang::tr{'invalid keepalive interval'});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Check if we have all required properties
|
||||
unless (exists $peer{"PRIVATE_KEY"}) {
|
||||
push(@errormessages, $Lang::tr{'wg missing private key'});
|
||||
}
|
||||
|
||||
unless (exists $peer{"PUBLIC_KEY"}) {
|
||||
push(@errormessages, $Lang::tr{'wg missing public key'});
|
||||
}
|
||||
|
||||
unless (exists $peer{"REMOTE_SUBNETS"}) {
|
||||
push(@errormessages, $Lang::tr{'wg missing allowed ips'});
|
||||
}
|
||||
|
||||
unless (exists $peer{"ENDPOINT_ADDRESS"}) {
|
||||
push(@errormessages, $Lang::tr{'wg missing endpoint address'});
|
||||
}
|
||||
|
||||
unless (exists $peer{"ENDPOINT_PORT"}) {
|
||||
push(@errormessages, $Lang::tr{'wg missing endpoint port'});
|
||||
}
|
||||
|
||||
return \%peer, @errormessages;
|
||||
}
|
||||
|
||||
sub get_free_port() {
|
||||
my @used_ports = ();
|
||||
|
||||
my $tries = 100;
|
||||
|
||||
# Collect all ports that are already in use
|
||||
foreach my $key (keys %peers) {
|
||||
push(@used_ports, $peers{$key}[5]);
|
||||
}
|
||||
|
||||
my ($port_start, $port_end) = @DEFAULT_PORTRANGE;
|
||||
|
||||
while ($tries-- > 0) {
|
||||
my $port = $port_start + int(rand($port_end - $port_start));
|
||||
|
||||
# Return the port unless it is already in use
|
||||
return $port unless (grep { $port == $_ } @used_ports);
|
||||
}
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
1;
|
||||
1
config/cfgroot/xdpdns-settings
Normal file
1
config/cfgroot/xdpdns-settings
Normal file
@@ -0,0 +1 @@
|
||||
ENABLE_DNSBLOCK=on
|
||||
1
config/cfgroot/xdpsni-settings
Normal file
1
config/cfgroot/xdpsni-settings
Normal file
@@ -0,0 +1 @@
|
||||
ENABLE_SNIBLOCK=on
|
||||
15
config/dnsdist/dnsdist-xsk.conf
Normal file
15
config/dnsdist/dnsdist-xsk.conf
Normal file
@@ -0,0 +1,15 @@
|
||||
if not inConfigCheck() then
|
||||
xsk = newXsk({ifName='green0', NIC_queue_id=0, frameNums=65536, xskMapPath='/sys/fs/bpf/dnsdist/xsk_map'})
|
||||
addLocal("0.0.0.0:53", {xskSocket=xsk})
|
||||
else
|
||||
addLocal("0.0.0.0:53")
|
||||
end
|
||||
|
||||
newServer("8.8.8.8:53")
|
||||
newServer("1.1.1.1:53")
|
||||
|
||||
---- newServer({address="8.8.8.8", healthCheckMode='lazy', checkInterval=1, lazyHealthCheckFailedInterval=30, rise=2, maxCheckFailures=3, lazyHealthCheckThreshold=30, lazyHealthCheckSampleSize=100, lazyHealthCheckMinSampleCount=10, lazyHealthCheckMode='TimeoutOnly'})
|
||||
|
||||
---- newServer({address="1.1.1.1", healthCheckMode='lazy', checkInterval=1, lazyHealthCheckFailedInterval=30, rise=2, maxCheckFailures=3, lazyHealthCheckThreshold=30, lazyHealthCheckSampleSize=100, lazyHealthCheckMinSampleCount=10, lazyHealthCheckMode='TimeoutOnly'})
|
||||
|
||||
|
||||
@@ -239,6 +239,8 @@ sub get_std_net_ip
|
||||
return "$netsettings{'BLUE_NETADDRESS'}/$netsettings{'BLUE_NETMASK'}";
|
||||
}elsif($val eq 'RED'){
|
||||
return "0.0.0.0/0";
|
||||
}elsif($val eq 'WGRW'){
|
||||
return $Wireguard::settings{'CLIENT_POOL'};
|
||||
}elsif($val =~ /OpenVPN/i){
|
||||
return "$ovpnsettings{'DOVPN_SUBNET'}";
|
||||
}elsif($val =~ /IPsec/i){
|
||||
@@ -259,6 +261,10 @@ sub get_interface
|
||||
if($net eq "$netsettings{'BLUE_NETADDRESS'}/$netsettings{'BLUE_NETMASK'}"){
|
||||
return "$netsettings{'BLUE_DEV'}";
|
||||
}
|
||||
# Wireguard
|
||||
if ($net eq $Wireguard::settings{'CLIENT_POOL'}) {
|
||||
return "wg0";
|
||||
}
|
||||
if($net eq "0.0.0.0/0") {
|
||||
return &get_external_interface();
|
||||
}
|
||||
@@ -385,6 +391,25 @@ sub get_address
|
||||
push(@ret, [$host_address, ""]);
|
||||
}
|
||||
|
||||
# WireGuard Peers
|
||||
} elsif ($key eq 'wg_peer' || $key eq 'wg_peer_src' || $key eq 'wg_peer_tgt') {
|
||||
my $peer = &Wireguard::get_peer_by_name($value);
|
||||
if (defined $peer) {
|
||||
my $remotes;
|
||||
|
||||
# Select the remote IP addresses
|
||||
if ($peer->{'TYPE'} eq 'host') {
|
||||
$remotes = $peer->{'CLIENT_ADDRESS'};
|
||||
} elsif ($peer->{'TYPE'} eq 'net') {
|
||||
$remotes = $peer->{'REMOTE_SUBNETS'};
|
||||
}
|
||||
|
||||
# Add all remotes
|
||||
foreach my $remote (@$remotes) {
|
||||
push(@ret, [$remote, $peer->{'INTERFACE'}]);
|
||||
}
|
||||
}
|
||||
|
||||
# OpenVPN networks.
|
||||
} elsif ($key ~~ ["ovpn_net_src", "ovpn_net_tgt", "OpenVPN static network"]) {
|
||||
my $network_address = &get_ovpn_net_ip($value, 1);
|
||||
|
||||
@@ -54,6 +54,7 @@ esac
|
||||
|
||||
HAVE_IPSEC="true"
|
||||
HAVE_OPENVPN="true"
|
||||
HAVE_WG="true"
|
||||
|
||||
# INPUT
|
||||
|
||||
@@ -97,6 +98,14 @@ case "${HAVE_OPENVPN},${POLICY}" in
|
||||
;;
|
||||
esac
|
||||
|
||||
# WireGuard INPUT
|
||||
case "${HAVE_WG},${POLICY}" in
|
||||
true,MODE1) ;;
|
||||
true,*)
|
||||
iptables -A POLICYIN -i wg+ -j ACCEPT
|
||||
;;
|
||||
esac
|
||||
|
||||
case "${FWPOLICY2}" in
|
||||
REJECT)
|
||||
if [ "${DROPINPUT}" = "on" ]; then
|
||||
@@ -149,6 +158,9 @@ case "${POLICY}" in
|
||||
# Grant access for OpenVPN connections
|
||||
iptables -A POLICYFWD -i tun+ -j ACCEPT
|
||||
|
||||
# Grant access for WireGuard
|
||||
iptables -A POLICYFWD -i wg+ -j ACCEPT
|
||||
|
||||
if [ -n "${IFACE}" ]; then
|
||||
if [ "${HAVE_BLUE}" = "true" ] && [ -n "${BLUE_DEV}" ]; then
|
||||
iptables -A POLICYFWD -i "${BLUE_DEV}" -s "${BLUE_NETADDRESS}/${BLUE_NETMASK}" -o "${IFACE}" -j ACCEPT
|
||||
|
||||
@@ -42,6 +42,8 @@ my $CHAIN = $CHAIN_FORWARD;
|
||||
my $CHAIN_NAT_SOURCE = "NAT_SOURCE";
|
||||
my $CHAIN_NAT_DESTINATION = "NAT_DESTINATION";
|
||||
my $CHAIN_MANGLE_NAT_DESTINATION_FIX = "NAT_DESTINATION";
|
||||
my $CHAIN_INSYNPROXY = "INSYNPROXY";
|
||||
my $CHAIN_RAWSYNPROXY = "RAWSYNPROXY";
|
||||
my @VALID_CHAINS = ($CHAIN_INPUT, $CHAIN_FORWARD, $CHAIN_OUTPUT);
|
||||
my @ANY_ADDRESSES = ("0.0.0.0/0.0.0.0", "0.0.0.0/0", "0/0");
|
||||
|
||||
@@ -218,6 +220,8 @@ sub flush {
|
||||
run("$IPTABLES -F $CHAIN_INPUT");
|
||||
run("$IPTABLES -F $CHAIN_FORWARD");
|
||||
run("$IPTABLES -F $CHAIN_OUTPUT");
|
||||
run("$IPTABLES -F $CHAIN_INSYNPROXY");
|
||||
run("$IPTABLES -t raw -F $CHAIN_RAWSYNPROXY");
|
||||
run("$IPTABLES -t nat -F $CHAIN_NAT_SOURCE");
|
||||
run("$IPTABLES -t nat -F $CHAIN_NAT_DESTINATION");
|
||||
run("$IPTABLES -t mangle -F $CHAIN_MANGLE_NAT_DESTINATION_FIX");
|
||||
@@ -297,6 +301,12 @@ sub buildrules {
|
||||
$NAT_MODE = uc($$hash{$key}[31]);
|
||||
}
|
||||
|
||||
# Check if XDP SYNPROXY is turned on
|
||||
my $SYNPROXY;
|
||||
if(exists($$hash{$key}[37])) {
|
||||
$SYNPROXY = ($$hash{$key}[37] eq 'ON');
|
||||
}
|
||||
|
||||
# Set up time constraints.
|
||||
my @time_options = ();
|
||||
if ($$hash{$key}[18] eq 'ON') {
|
||||
@@ -608,6 +618,23 @@ sub buildrules {
|
||||
}
|
||||
run("$IPTABLES -A $chain @options @source_intf_options @destination_intf_options -j $target");
|
||||
|
||||
if ($SYNPROXY) {
|
||||
my $dport = &get_external_port($hash, $key);
|
||||
my @raw_options = ("-p", "tcp", "-m", "tcp", "--syn");
|
||||
my @in_options = ("-p", "tcp", "-m", "tcp");
|
||||
my @options = ("--sack-perm", "--timestamp", "--wscale", "7", "--mss", "1460");
|
||||
push(@raw_options, "--dport", "$dport");
|
||||
push(@in_options, "--dport", "$dport", "-m", "state", "--state", "INVALID,UNTRACKED");
|
||||
if ($LOG) {
|
||||
run("$IPTABLES -t raw -A $CHAIN_RAWSYNPROXY -i $RED_DEV @raw_options -j LOG --log-prefix '$CHAIN_RAWSYNPROXY '");
|
||||
}
|
||||
run("$IPTABLES -t raw -A $CHAIN_RAWSYNPROXY -i $RED_DEV @raw_options -j CT --notrack");
|
||||
if ($LOG) {
|
||||
run("$IPTABLES -A $CHAIN_INSYNPROXY -i $RED_DEV @in_options -j LOG --log-prefix '$CHAIN_RAWSYNPROXY ' @options");
|
||||
}
|
||||
run("$IPTABLES -A $CHAIN_INSYNPROXY -i $RED_DEV @in_options -j SYNPROXY @options");
|
||||
}
|
||||
|
||||
# Handle forwarding rules and add corresponding rules for firewall access.
|
||||
if ($chain eq $CHAIN_FORWARD) {
|
||||
# If the firewall is part of the destination subnet and access to the destination network
|
||||
@@ -945,6 +972,22 @@ sub get_dnat_target_port {
|
||||
}
|
||||
}
|
||||
|
||||
sub get_external_port {
|
||||
my $hash = shift;
|
||||
my $key = shift;
|
||||
|
||||
if ($$hash{$key}[14] eq "TGT_PORT") {
|
||||
my $port = $$hash{$key}[15];
|
||||
my $external_port = $$hash{$key}[30];
|
||||
|
||||
if ($external_port && ($port ne $external_port)) {
|
||||
return $external_port;
|
||||
} else {
|
||||
return $port;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub add_dnat_mangle_rules {
|
||||
my $nat_address = shift;
|
||||
my $interface = shift;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
GRUB_TIMEOUT=5
|
||||
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
|
||||
GRUB_DEFAULT=saved
|
||||
GRUB_CMDLINE_LINUX="rd.auto panic=10"
|
||||
GRUB_CMDLINE_LINUX="rd.auto crashkernel=512M nmi_watchdog=1 softlockup_panic=1 panic=10"
|
||||
GRUB_DISABLE_RECOVERY="true"
|
||||
GRUB_BACKGROUND="/boot/grub/splash.png"
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 140 KiB After Width: | Height: | Size: 436 KiB |
883
config/kernel/bpfire-logo-ascii.ppm
Normal file
883
config/kernel/bpfire-logo-ascii.ppm
Normal file
@@ -0,0 +1,883 @@
|
||||
P3
|
||||
63 80
|
||||
255
|
||||
161 18 12 165 19 14 170 20 15 171 21 16 170 20 15 171 21 16
|
||||
173 20 15 173 20 15 171 21 16 171 21 16 171 21 16 173 19 15
|
||||
173 20 15 173 19 15 176 18 12 173 19 15 173 20 15 173 20 15
|
||||
177 20 14 177 20 14 177 20 14 177 20 14 177 20 14 177 20 14
|
||||
177 20 14 177 20 14 177 20 14 176 18 12 174 18 12 176 17 11
|
||||
176 18 12 177 20 14 183 19 13 183 19 13 183 19 13 183 19 13
|
||||
183 19 13 183 19 13 183 19 13 183 19 13 183 19 13 177 20 14
|
||||
177 20 14 183 19 13 177 20 14 173 19 15 177 20 14 177 20 14
|
||||
177 20 14 173 19 15 177 20 14 177 20 14 177 20 14 177 20 14
|
||||
177 20 14 177 20 14 177 20 14 173 19 15 177 20 14 177 20 14
|
||||
177 20 14 168 18 14 164 16 11
|
||||
161 18 12 165 19 14 170 20 15 171 21 16 170 20 15 170 20 15
|
||||
171 21 16 171 21 16 169 21 14 171 21 16 170 20 15 170 20 15
|
||||
170 20 15 173 20 15 173 19 15 173 20 15 173 20 15 173 19 15
|
||||
173 19 15 173 19 15 177 20 14 176 18 12 176 18 12 176 18 12
|
||||
177 20 14 177 20 14 176 18 12 176 17 11 176 17 11 176 17 11
|
||||
176 17 11 176 18 12 177 20 14 177 20 14 177 20 14 177 20 14
|
||||
177 20 14 183 19 13 177 20 14 177 20 14 177 20 14 177 20 14
|
||||
177 20 14 176 18 12 173 19 15 173 19 15 173 19 15 177 20 14
|
||||
173 19 15 173 19 15 173 19 15 173 19 15 176 18 12 177 20 14
|
||||
177 20 14 177 20 14 177 20 14 173 19 15 173 20 15 173 20 15
|
||||
173 19 15 164 16 11 183 19 13
|
||||
160 19 13 168 22 16 168 22 16 171 21 16 168 22 16 168 22 16
|
||||
168 22 16 168 22 16 168 22 16 168 22 16 171 21 16 171 21 16
|
||||
168 22 16 171 21 16 171 21 16 171 21 16 173 20 15 173 20 15
|
||||
173 20 15 173 19 15 173 20 15 173 20 15 173 19 15 173 19 15
|
||||
173 19 15 173 19 15 176 18 12 173 19 15 174 18 12 176 17 11
|
||||
174 18 12 173 19 15 176 17 11 177 20 14 177 20 14 177 20 14
|
||||
177 20 14 177 20 14 177 20 14 177 20 14 177 20 14 173 20 15
|
||||
173 20 15 173 20 15 173 20 15 171 21 16 171 21 16 171 21 16
|
||||
171 21 16 170 20 15 173 20 15 173 20 15 173 20 15 173 20 15
|
||||
173 20 15 173 20 15 173 20 15 171 21 16 171 21 16 173 20 15
|
||||
156 15 13 183 19 13 183 19 13
|
||||
160 19 13 168 22 16 168 22 16 168 22 16 168 22 16 168 22 16
|
||||
168 22 16 168 22 16 168 22 16 168 22 16 168 22 16 168 22 16
|
||||
168 22 16 171 21 16 171 21 16 171 21 16 173 20 15 171 21 16
|
||||
173 20 15 173 20 15 173 20 15 173 20 15 173 19 15 173 19 15
|
||||
173 19 15 173 19 15 174 18 12 174 18 12 176 17 11 173 19 15
|
||||
174 18 12 173 19 15 176 24 12 173 19 15 176 18 12 177 20 14
|
||||
177 20 14 177 20 14 177 20 14 177 20 14 177 20 14 173 20 15
|
||||
173 20 15 173 20 15 173 20 15 171 21 16 173 20 15 173 20 15
|
||||
171 21 16 171 21 16 171 21 16 173 20 15 173 20 15 173 20 15
|
||||
171 21 16 173 20 15 173 20 15 171 21 16 177 20 14 157 19 14
|
||||
183 19 13 183 19 13 183 19 13
|
||||
156 15 13 162 20 14 168 22 16 168 22 16 168 22 16 168 22 16
|
||||
168 22 16 171 21 16 168 22 16 168 22 16 168 22 16 168 22 16
|
||||
168 22 16 171 21 16 171 21 16 173 20 15 173 20 15 171 21 16
|
||||
173 20 15 173 20 15 173 20 15 173 20 15 173 19 15 173 19 15
|
||||
173 19 15 168 18 14 168 18 14 176 17 11 167 52 24 176 17 11
|
||||
176 17 11 176 18 12 173 92 60 177 20 14 177 20 14 176 17 11
|
||||
177 20 14 177 20 14 177 20 14 177 20 14 177 20 14 173 20 15
|
||||
173 20 15 173 19 15 173 19 15 173 20 15 173 19 15 173 20 15
|
||||
171 21 16 171 21 16 171 21 16 173 20 15 171 21 16 171 21 16
|
||||
171 21 16 171 21 16 171 21 16 173 20 15 164 19 14 164 16 11
|
||||
183 19 13 183 19 13 183 19 13
|
||||
157 19 14 162 20 14 168 22 16 168 22 16 168 22 16 168 22 16
|
||||
168 22 16 168 22 16 168 22 16 168 22 16 168 22 16 168 22 16
|
||||
168 22 16 171 21 16 171 21 16 171 21 16 171 21 16 164 16 11
|
||||
173 20 15 173 19 15 171 21 16 173 19 15 173 19 15 173 19 15
|
||||
164 16 11 167 52 24 167 52 24 164 16 11 173 92 60 211 179 117
|
||||
176 17 11 176 18 12 164 16 11 167 52 24 175 97 50 176 17 11
|
||||
177 20 14 177 20 14 173 19 15 173 19 15 173 19 15 173 20 15
|
||||
176 17 11 176 17 11 173 20 15 173 19 15 173 20 15 171 21 16
|
||||
171 21 16 171 21 16 173 20 15 173 20 15 171 21 16 171 21 16
|
||||
171 21 16 170 20 15 171 21 16 168 22 16 152 14 13 183 19 13
|
||||
183 19 13 183 19 13 183 19 13
|
||||
156 20 14 162 20 14 168 22 16 168 22 16 160 22 16 160 22 16
|
||||
168 22 16 168 22 16 168 22 16 168 22 16 168 22 16 168 22 16
|
||||
168 22 16 171 21 16 168 22 16 168 18 14 174 18 12 163 56 28
|
||||
173 19 15 168 18 14 176 17 11 183 19 13 164 16 11 168 18 14
|
||||
164 16 11 175 97 50 175 97 50 164 16 11 176 17 11 238 229 170
|
||||
215 186 121 183 19 13 176 17 11 167 52 24 213 153 88 176 17 11
|
||||
177 20 14 176 17 11 183 19 13 183 19 13 164 16 11 176 17 11
|
||||
167 52 24 176 24 12 176 17 11 173 20 15 173 20 15 171 21 16
|
||||
171 21 16 171 21 16 171 21 16 170 20 15 171 21 16 171 21 16
|
||||
171 21 16 168 22 16 168 22 16 151 18 14 183 19 13 183 19 13
|
||||
183 19 13 183 19 13 183 19 13
|
||||
152 20 15 160 22 16 160 22 16 160 22 16 168 22 16 162 20 14
|
||||
168 22 16 168 22 16 168 22 16 168 22 16 168 22 16 168 22 16
|
||||
168 22 16 168 22 16 168 18 14 176 24 12 206 199 148 179 118 76
|
||||
164 16 11 176 24 12 191 130 98 162 137 108 191 130 98 164 16 11
|
||||
164 16 11 176 24 12 176 24 12 177 20 14 183 19 13 211 179 117
|
||||
254 255 240 175 96 57 176 17 11 183 19 13 167 52 24 176 17 11
|
||||
176 17 11 175 96 57 162 137 108 169 133 98 167 52 24 164 16 11
|
||||
167 52 24 206 199 148 167 52 24 176 17 11 173 20 15 173 20 15
|
||||
171 21 16 171 21 16 171 21 16 168 22 16 171 21 16 171 21 16
|
||||
168 22 16 168 22 16 152 20 15 176 17 11 183 19 13 183 19 13
|
||||
183 19 13 183 19 13 183 19 13
|
||||
151 18 14 159 21 16 160 22 16 160 22 16 160 22 16 168 22 16
|
||||
162 20 14 168 22 16 168 22 16 168 22 16 167 21 14 168 22 16
|
||||
168 22 16 168 22 16 164 16 11 191 130 98 243 238 185 176 17 11
|
||||
164 16 11 191 130 98 97 69 52 0 0 0 131 94 71 176 111 73
|
||||
154 14 11 168 18 14 176 17 11 176 111 73 183 19 13 215 186 121
|
||||
254 255 240 221 205 133 183 19 13 176 17 11 164 16 11 164 16 11
|
||||
183 19 13 158 125 90 0 0 0 0 0 0 162 137 108 183 19 13
|
||||
164 16 11 199 143 96 225 212 158 176 17 11 171 21 16 170 20 15
|
||||
171 21 16 171 21 16 170 20 15 171 21 16 171 21 16 168 22 16
|
||||
168 22 16 162 20 14 161 18 12 183 19 13 183 19 13 183 19 13
|
||||
183 19 13 183 19 13 128 8 8
|
||||
151 18 14 156 20 14 160 21 14 160 22 16 160 22 16 168 22 16
|
||||
160 22 16 160 22 16 168 22 16 168 22 16 168 22 16 168 22 16
|
||||
165 19 14 165 19 14 164 16 11 225 212 158 225 212 158 176 17 11
|
||||
183 19 13 131 94 71 91 31 21 243 238 185 91 31 21 162 137 108
|
||||
183 19 13 176 24 12 176 24 12 176 17 11 183 19 13 247 246 193
|
||||
254 255 233 238 229 170 183 19 13 167 52 24 176 24 12 176 17 11
|
||||
199 143 96 91 31 21 225 212 158 162 137 108 97 69 52 173 92 60
|
||||
176 17 11 199 143 96 243 238 185 183 19 13 173 20 15 170 20 15
|
||||
170 20 15 171 21 16 167 21 14 167 21 14 167 21 14 164 19 14
|
||||
168 22 16 150 16 12 183 19 13 183 19 13 183 19 13 183 19 13
|
||||
183 19 13 147 12 10 89 3 6
|
||||
151 18 14 152 20 15 159 21 16 162 20 14 164 19 14 160 22 16
|
||||
160 22 16 167 21 14 168 22 16 168 22 16 168 22 16 165 19 14
|
||||
164 19 14 164 19 14 164 16 11 199 163 109 249 249 214 183 19 13
|
||||
176 24 12 131 94 71 111 0 3 183 19 13 106 7 8 97 69 52
|
||||
199 163 109 211 179 117 183 19 13 183 19 13 211 179 117 254 255 233
|
||||
253 255 226 238 229 170 183 19 13 183 19 13 183 19 13 199 143 96
|
||||
97 69 52 77 0 3 183 19 13 171 21 16 97 69 52 173 92 60
|
||||
176 17 11 238 229 170 225 212 158 176 17 11 173 20 15 170 20 15
|
||||
170 20 15 171 21 16 168 18 14 165 19 14 164 19 14 168 18 14
|
||||
150 16 12 183 19 13 183 19 13 183 19 13 183 19 13 183 19 13
|
||||
164 16 11 109 5 7 77 0 3
|
||||
151 18 14 152 20 15 159 21 16 162 20 14 162 20 14 160 22 16
|
||||
160 22 16 167 21 14 165 19 14 167 21 14 164 19 14 161 18 12
|
||||
165 19 14 164 19 14 164 16 11 176 24 12 249 249 214 191 130 98
|
||||
154 14 11 162 137 108 0 0 0 107 0 4 0 0 0 77 0 3
|
||||
0 0 0 206 199 148 175 97 50 213 153 88 254 255 233 249 249 214
|
||||
254 255 233 215 186 121 193 134 84 167 52 24 191 130 98 91 31 21
|
||||
77 0 3 0 0 0 77 0 3 0 0 0 158 125 90 183 19 13
|
||||
175 96 57 254 255 210 167 52 24 176 17 11 170 20 15 168 18 14
|
||||
168 18 14 171 21 16 168 18 14 164 19 14 167 21 14 156 15 13
|
||||
174 18 12 183 19 13 183 19 13 183 19 13 183 19 13 183 19 13
|
||||
119 5 9 77 0 3 77 0 3
|
||||
151 18 14 156 20 14 159 21 16 160 19 13 162 20 14 162 20 14
|
||||
162 20 14 164 19 14 167 21 14 168 22 16 160 19 13 156 15 13
|
||||
164 19 14 161 18 12 156 15 13 133 0 5 176 111 73 243 238 185
|
||||
133 0 5 173 92 60 162 137 108 97 69 52 162 137 108 91 31 21
|
||||
77 0 3 0 0 0 202 183 123 254 255 223 250 251 219 249 249 214
|
||||
254 255 233 193 134 84 215 186 121 225 212 158 91 31 21 77 0 3
|
||||
78 2 7 158 125 90 97 69 52 131 94 71 173 92 60 154 14 11
|
||||
231 215 150 213 153 88 154 14 11 164 16 11 164 16 11 168 18 14
|
||||
168 18 14 168 18 14 164 16 11 167 21 14 162 20 14 156 15 13
|
||||
183 19 13 183 19 13 183 19 13 183 19 13 183 19 13 128 6 9
|
||||
78 2 7 77 0 3 78 2 7
|
||||
150 16 12 152 20 15 159 21 16 159 21 16 160 19 13 162 20 14
|
||||
160 22 16 160 22 16 165 19 14 168 22 16 164 16 11 156 15 13
|
||||
164 16 11 154 14 11 147 12 10 143 19 14 154 43 26 247 246 193
|
||||
150 53 31 107 0 4 173 92 60 199 163 109 147 67 48 202 183 123
|
||||
97 69 52 77 0 3 97 69 52 252 253 227 254 255 210 254 255 223
|
||||
238 229 170 183 19 13 232 217 158 131 94 71 77 0 3 78 2 7
|
||||
162 137 108 147 67 48 176 111 73 207 156 97 133 0 5 164 16 11
|
||||
238 229 170 173 92 60 147 12 10 154 14 11 167 52 24 174 18 12
|
||||
164 16 11 169 21 14 171 21 16 168 18 14 144 14 14 183 19 13
|
||||
183 19 13 183 19 13 183 19 13 183 19 13 147 12 10 93 4 6
|
||||
77 0 3 78 2 7 91 2 10
|
||||
150 16 12 152 20 15 157 23 16 159 21 16 159 21 16 162 20 14
|
||||
160 22 16 162 20 14 164 19 14 168 22 16 191 130 98 154 14 11
|
||||
163 56 28 199 163 109 133 0 5 151 28 16 173 92 60 254 255 210
|
||||
147 67 48 107 0 4 199 143 96 154 63 38 80 0 2 193 134 84
|
||||
237 235 180 78 2 7 77 0 3 162 137 108 253 255 226 253 254 208
|
||||
193 134 84 183 19 13 202 183 123 91 31 21 77 0 3 162 137 108
|
||||
193 134 84 92 0 2 102 0 4 211 179 117 167 52 24 164 16 11
|
||||
247 246 193 199 143 96 159 29 16 164 16 11 225 212 158 167 52 24
|
||||
164 16 11 199 143 96 167 52 24 147 12 10 183 19 13 183 19 13
|
||||
183 19 13 183 19 13 183 19 13 164 16 11 102 4 5 77 0 3
|
||||
78 2 7 91 2 10 99 1 11
|
||||
150 16 12 152 20 15 157 23 16 157 23 16 159 21 16 160 22 16
|
||||
159 21 16 160 21 14 161 18 12 168 22 16 249 249 214 173 92 60
|
||||
161 18 12 154 63 38 139 9 7 154 14 11 238 229 170 252 252 206
|
||||
139 27 18 131 14 12 247 246 193 150 53 31 116 3 5 211 173 103
|
||||
237 223 121 162 137 108 0 0 0 97 69 52 250 251 219 254 255 223
|
||||
193 134 84 183 19 13 158 125 90 77 0 3 97 69 52 224 209 127
|
||||
208 170 99 137 32 21 120 0 3 243 238 185 173 92 60 164 16 11
|
||||
238 229 170 247 246 193 171 21 16 176 17 11 167 52 24 176 17 11
|
||||
167 52 24 252 253 227 173 92 60 176 17 11 183 19 13 183 19 13
|
||||
183 19 13 183 19 13 183 19 13 114 7 7 77 0 3 78 2 7
|
||||
87 1 5 99 1 11 133 0 5
|
||||
150 16 12 151 18 14 159 21 16 156 20 14 159 21 16 162 20 14
|
||||
160 21 14 160 22 16 164 16 11 176 111 73 254 255 240 176 111 73
|
||||
154 14 11 164 16 11 167 52 24 238 229 170 254 255 233 206 199 148
|
||||
123 0 2 133 0 5 238 229 170 199 163 109 139 9 7 237 223 121
|
||||
213 153 88 221 205 133 91 31 21 77 0 3 206 199 148 206 199 148
|
||||
162 137 108 202 183 123 97 69 52 0 0 0 187 167 103 213 153 88
|
||||
237 223 121 163 56 28 176 111 73 254 255 233 176 24 12 154 14 11
|
||||
199 163 109 254 255 240 238 229 170 167 52 24 176 17 11 176 24 12
|
||||
173 92 60 254 255 240 215 186 121 183 19 13 183 19 13 183 19 13
|
||||
183 19 13 183 19 13 127 5 8 78 2 7 78 2 7 78 2 7
|
||||
99 1 11 128 6 9 122 7 7
|
||||
145 15 12 152 20 15 156 20 14 156 20 14 159 21 16 162 20 14
|
||||
160 19 13 160 22 16 164 16 11 215 186 121 254 255 240 163 56 28
|
||||
176 17 11 175 97 50 243 238 185 254 255 223 254 255 223 173 92 60
|
||||
139 9 7 154 43 26 163 56 28 247 246 193 167 52 24 219 195 113
|
||||
213 153 88 241 232 158 97 69 52 77 0 3 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 91 31 21 225 212 158 213 153 88
|
||||
237 223 121 167 52 24 237 235 180 199 143 96 176 24 12 177 20 14
|
||||
167 52 24 249 249 214 253 255 226 243 238 185 167 52 24 183 19 13
|
||||
167 52 24 252 253 227 243 238 185 183 19 13 183 19 13 183 19 13
|
||||
183 19 13 147 12 10 87 1 5 78 2 7 78 2 7 99 1 11
|
||||
128 6 9 131 9 10 129 12 11
|
||||
145 15 12 151 18 14 156 20 14 159 21 16 159 21 16 162 20 14
|
||||
160 19 13 162 20 14 164 16 11 215 186 121 211 179 117 176 17 11
|
||||
183 19 13 215 186 121 253 255 226 254 255 210 238 229 170 164 16 11
|
||||
199 163 109 173 92 60 139 9 7 199 143 96 173 92 60 192 140 79
|
||||
237 223 121 97 69 52 0 0 0 91 31 21 173 92 60 211 179 117
|
||||
211 179 117 191 130 98 106 7 8 0 0 0 91 31 21 225 212 158
|
||||
237 223 121 175 96 57 225 212 158 176 17 11 163 56 28 206 199 148
|
||||
176 17 11 206 199 148 254 255 223 254 255 223 215 186 121 183 19 13
|
||||
176 24 12 213 153 88 232 217 158 183 19 13 183 19 13 183 19 13
|
||||
176 17 11 95 4 6 78 2 7 78 2 7 99 1 11 122 8 8
|
||||
131 9 10 125 8 10 131 9 10
|
||||
145 15 12 151 18 14 156 20 14 156 20 14 160 21 14 160 19 13
|
||||
164 19 14 156 15 13 147 12 10 164 16 11 164 16 11 183 19 13
|
||||
183 19 13 243 238 185 254 255 210 254 255 223 199 163 109 176 17 11
|
||||
249 249 214 167 52 24 139 9 7 199 143 96 193 134 84 213 153 88
|
||||
97 69 52 91 31 21 191 130 98 183 19 13 183 19 13 211 179 117
|
||||
249 249 214 173 92 60 183 19 13 173 92 60 97 69 52 0 0 0
|
||||
199 163 109 213 153 88 206 199 148 154 14 11 183 19 13 249 249 214
|
||||
167 52 24 193 134 84 254 255 223 252 252 206 252 252 206 175 97 50
|
||||
183 19 13 183 19 13 183 19 13 183 19 13 183 19 13 183 19 13
|
||||
122 8 8 78 2 7 78 2 7 95 4 6 119 5 9 137 11 10
|
||||
125 8 10 137 11 10 142 10 9
|
||||
145 15 12 151 18 14 152 20 15 156 20 14 160 21 14 168 22 16
|
||||
164 16 11 176 24 12 175 96 57 176 111 73 193 134 84 175 96 57
|
||||
175 96 57 249 249 214 252 252 206 254 255 223 199 143 96 183 19 13
|
||||
254 255 233 199 143 96 163 56 28 247 246 193 215 186 121 97 69 52
|
||||
91 31 21 213 153 88 183 19 13 173 92 60 207 156 97 225 212 158
|
||||
254 255 240 199 143 96 211 179 117 183 19 13 175 96 57 129 78 48
|
||||
91 31 21 221 205 133 249 249 214 175 96 57 191 130 98 254 255 240
|
||||
173 92 60 193 134 84 254 255 223 247 246 193 253 254 208 213 153 88
|
||||
175 97 50 213 153 88 213 153 88 213 153 88 175 97 50 161 18 12
|
||||
106 7 8 89 3 6 93 4 6 114 7 7 139 9 7 125 8 10
|
||||
138 12 11 142 10 9 164 16 11
|
||||
144 16 12 152 20 15 156 20 14 160 22 16 168 22 16 176 24 12
|
||||
175 96 57 162 137 108 97 69 52 97 69 52 97 69 52 131 94 71
|
||||
191 177 112 250 251 219 254 255 223 254 255 223 211 179 117 183 19 13
|
||||
243 238 185 253 254 208 254 255 223 235 226 137 182 147 96 0 0 0
|
||||
175 97 50 147 12 10 102 0 4 183 19 13 183 19 13 215 186 121
|
||||
249 249 214 173 92 60 183 19 13 139 9 7 99 0 3 173 92 60
|
||||
105 45 32 131 94 71 249 243 164 250 251 219 254 255 210 244 241 169
|
||||
183 19 13 211 173 103 254 255 210 252 252 206 254 255 210 206 199 148
|
||||
131 94 71 97 69 52 97 69 52 97 69 52 162 137 108 191 130 98
|
||||
114 7 7 111 14 13 111 14 13 137 11 10 128 8 8 137 13 11
|
||||
145 11 11 164 16 11 156 15 13
|
||||
143 19 14 152 20 15 157 23 16 168 22 16 176 24 12 167 52 24
|
||||
158 125 90 0 0 0 97 69 52 162 137 108 158 125 90 97 69 52
|
||||
0 0 0 91 31 21 191 177 112 254 255 223 252 252 206 183 19 13
|
||||
213 153 88 237 223 121 237 223 121 216 189 107 97 69 52 132 32 17
|
||||
78 2 7 91 31 21 162 137 108 91 31 21 183 19 13 173 92 60
|
||||
191 130 98 183 19 13 78 2 7 131 94 71 131 94 71 0 0 0
|
||||
141 65 38 91 31 21 219 195 113 237 223 121 237 223 121 213 153 88
|
||||
183 19 13 243 238 185 254 255 210 206 199 148 91 31 21 0 0 0
|
||||
97 69 52 131 94 71 162 137 108 131 94 71 0 0 0 97 69 52
|
||||
173 92 60 135 17 11 143 19 14 139 9 7 131 14 12 142 13 12
|
||||
164 16 11 164 16 11 156 15 13
|
||||
143 19 14 152 20 15 159 29 16 168 22 16 176 24 12 175 96 57
|
||||
131 94 71 206 199 148 249 249 214 254 255 240 254 255 240 254 255 233
|
||||
249 249 214 162 137 108 0 0 0 91 31 21 225 212 158 243 238 185
|
||||
213 153 88 213 153 88 213 153 88 208 170 99 91 31 21 106 7 8
|
||||
0 0 0 225 212 158 254 255 240 206 199 148 77 0 3 191 130 98
|
||||
215 186 121 133 0 5 131 94 71 254 255 240 254 255 240 97 69 52
|
||||
77 0 3 78 2 7 162 137 108 213 153 88 216 189 107 213 153 88
|
||||
232 217 158 237 235 180 97 69 52 0 0 0 158 125 90 243 238 185
|
||||
254 255 240 254 255 240 254 255 233 249 249 214 206 199 148 97 69 52
|
||||
176 111 73 152 17 12 150 16 12 125 8 10 144 14 14 156 15 13
|
||||
168 18 14 161 18 12 183 19 13
|
||||
143 19 14 157 23 16 159 29 16 168 22 16 174 18 12 175 96 57
|
||||
131 94 71 206 199 148 225 212 158 206 199 148 249 249 214 250 251 219
|
||||
254 255 223 254 255 233 249 249 214 131 94 71 0 0 0 162 137 108
|
||||
247 246 193 213 153 88 175 97 50 182 147 96 78 2 7 77 0 3
|
||||
0 0 0 237 235 180 254 255 240 237 235 180 0 0 0 183 19 13
|
||||
183 19 13 77 0 3 162 137 108 254 255 240 254 255 240 97 69 52
|
||||
0 0 0 77 0 3 131 94 71 213 153 88 213 153 88 237 223 121
|
||||
206 199 148 0 0 0 97 69 52 249 249 214 254 255 240 254 255 223
|
||||
250 251 219 249 249 214 206 199 148 206 199 148 206 199 148 97 69 52
|
||||
176 111 73 164 16 11 138 12 11 146 12 11 147 12 10 173 20 15
|
||||
156 15 13 183 19 13 150 16 12
|
||||
143 19 14 152 20 15 157 23 16 159 29 16 164 16 11 173 92 60
|
||||
131 94 71 162 137 108 237 235 180 206 199 148 206 199 148 254 255 223
|
||||
250 251 219 249 249 214 250 251 219 254 255 240 206 199 148 0 0 0
|
||||
131 94 71 213 153 88 213 153 88 162 137 108 77 0 3 0 0 0
|
||||
0 0 0 131 94 71 249 249 214 131 94 71 0 0 0 168 18 14
|
||||
183 19 13 0 0 0 0 0 0 237 235 180 206 199 148 91 31 21
|
||||
0 0 0 77 0 3 97 69 52 215 186 121 213 153 88 162 137 108
|
||||
0 0 0 162 137 108 254 255 240 254 255 223 249 249 214 249 249 214
|
||||
254 255 223 225 212 158 206 199 148 237 235 180 206 199 148 97 69 52
|
||||
175 96 57 133 0 5 156 15 13 147 12 10 168 18 14 160 19 13
|
||||
183 19 13 160 19 13 105 1 7
|
||||
144 16 12 152 20 15 152 20 15 157 23 16 154 14 11 176 108 61
|
||||
158 125 90 131 94 71 249 249 214 237 235 180 206 199 148 206 199 148
|
||||
253 255 226 254 255 223 250 251 219 249 249 214 254 255 233 249 249 214
|
||||
91 31 21 97 69 52 215 186 121 143 100 73 78 2 7 0 0 0
|
||||
162 137 108 0 0 0 0 0 0 131 94 71 97 69 52 123 0 2
|
||||
183 19 13 0 0 0 162 137 108 0 0 0 0 0 0 131 94 71
|
||||
97 69 52 0 0 0 97 69 52 231 215 150 131 94 71 0 0 0
|
||||
237 235 180 254 255 240 249 249 214 250 251 219 250 251 219 254 255 223
|
||||
237 235 180 206 199 148 237 235 180 249 249 214 162 137 108 97 69 52
|
||||
193 134 84 142 10 9 164 16 11 168 18 14 164 19 14 174 18 12
|
||||
176 24 12 109 5 7 119 5 9
|
||||
144 16 12 147 20 17 147 20 17 150 16 12 154 43 26 211 179 117
|
||||
179 118 76 97 69 52 206 199 148 206 199 148 237 235 180 206 199 148
|
||||
206 199 148 254 255 223 254 255 223 250 251 219 250 251 219 254 255 223
|
||||
206 199 148 91 31 21 97 69 52 206 199 148 0 0 0 91 31 21
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 156 15 13
|
||||
183 19 13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 131 94 71 162 137 108 0 0 0 206 199 148
|
||||
250 251 219 254 255 223 254 255 223 254 255 223 254 255 223 237 235 180
|
||||
206 199 148 237 235 180 206 199 148 206 199 148 97 69 52 131 94 71
|
||||
199 163 109 173 92 60 164 16 11 173 20 15 164 16 11 183 19 13
|
||||
116 9 9 105 1 7 119 5 9
|
||||
141 15 12 143 19 14 147 20 17 139 9 7 173 92 60 219 202 125
|
||||
173 92 60 97 69 52 97 69 52 206 199 148 206 199 148 249 249 214
|
||||
237 235 180 206 199 148 237 235 180 253 255 226 249 249 214 206 199 148
|
||||
237 235 180 253 255 226 97 69 52 97 69 52 78 2 7 91 31 21
|
||||
97 69 52 0 0 0 0 0 0 0 0 0 0 0 0 183 19 13
|
||||
183 19 13 91 31 21 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
97 69 52 77 0 3 91 31 21 91 31 21 243 238 185 249 249 214
|
||||
206 199 148 237 235 180 253 255 226 249 249 214 206 199 148 206 199 148
|
||||
249 249 214 206 199 148 206 199 148 162 137 108 97 69 52 173 92 60
|
||||
211 173 103 199 143 96 176 17 11 165 19 14 183 19 13 135 17 11
|
||||
99 1 11 119 5 9 117 6 7
|
||||
141 15 12 141 15 12 143 19 14 139 9 7 163 56 28 231 215 150
|
||||
124 14 13 153 103 68 0 0 0 162 137 108 206 199 148 206 199 148
|
||||
249 249 214 250 251 219 206 199 148 206 199 148 162 137 108 249 249 214
|
||||
253 255 226 250 251 219 252 253 227 97 69 52 0 0 0 78 2 7
|
||||
97 69 52 97 69 52 97 69 52 97 69 52 78 2 7 183 19 13
|
||||
183 19 13 145 11 11 97 69 52 97 69 52 97 69 52 97 69 52
|
||||
91 31 21 77 0 3 0 0 0 237 235 180 253 255 226 254 255 223
|
||||
249 249 214 206 199 148 162 137 108 206 199 148 252 253 227 250 251 219
|
||||
206 199 148 206 199 148 206 199 148 91 31 21 131 94 71 176 17 11
|
||||
215 186 121 175 96 57 164 16 11 183 19 13 159 29 16 93 4 6
|
||||
114 7 7 119 5 9 125 8 10
|
||||
137 13 11 138 15 12 141 15 12 143 13 11 147 12 10 154 63 38
|
||||
111 0 3 175 96 57 133 82 52 91 31 21 206 199 148 206 199 148
|
||||
206 199 148 237 235 180 206 199 148 206 199 148 206 199 148 206 199 148
|
||||
206 199 148 237 235 180 250 251 219 249 249 214 0 0 0 78 2 7
|
||||
78 2 7 97 69 52 97 69 52 0 0 0 183 19 13 183 19 13
|
||||
183 19 13 183 19 13 78 2 7 97 69 52 97 69 52 0 0 0
|
||||
91 2 10 0 0 0 206 199 148 254 255 233 237 235 180 206 199 148
|
||||
206 199 148 206 199 148 237 235 180 206 199 148 206 199 148 206 199 148
|
||||
206 199 148 206 199 148 97 69 52 97 69 52 192 140 79 164 16 11
|
||||
167 52 24 176 24 12 183 19 13 176 24 12 95 4 6 106 7 8
|
||||
117 6 7 125 8 10 134 12 11
|
||||
134 12 11 138 15 12 144 16 12 146 12 11 131 10 9 122 7 7
|
||||
128 8 8 192 140 79 216 189 107 91 31 21 97 69 52 206 199 148
|
||||
162 137 108 162 137 108 237 235 180 253 255 226 250 251 219 249 249 214
|
||||
225 212 158 206 199 148 206 199 148 237 235 180 162 137 108 0 0 0
|
||||
99 1 11 111 0 3 123 0 2 183 19 13 183 19 13 145 11 11
|
||||
91 2 10 183 19 13 183 19 13 111 0 3 92 0 2 111 14 13
|
||||
0 0 0 131 94 71 249 249 214 206 199 148 206 199 148 206 199 148
|
||||
249 249 214 250 251 219 254 255 223 249 249 214 162 137 108 162 137 108
|
||||
206 199 148 131 94 71 91 31 21 211 173 103 217 193 123 167 52 24
|
||||
147 12 10 174 18 12 183 19 13 111 14 13 102 4 5 114 7 7
|
||||
119 5 9 131 9 10 142 13 12
|
||||
131 14 12 138 15 12 152 14 13 139 9 7 131 14 12 131 10 9
|
||||
152 48 27 231 215 150 187 167 103 208 170 99 91 31 21 0 0 0
|
||||
162 137 108 206 199 148 206 199 148 206 199 148 237 235 180 237 235 180
|
||||
249 249 214 250 251 219 237 235 180 206 199 148 206 199 148 97 69 52
|
||||
0 0 0 111 14 13 183 19 13 183 19 13 183 19 13 78 2 7
|
||||
0 0 0 183 19 13 183 19 13 183 19 13 144 14 14 78 2 7
|
||||
0 0 0 162 137 108 206 199 148 237 235 180 252 253 227 254 255 233
|
||||
249 249 214 237 235 180 225 212 158 206 199 148 206 199 148 162 137 108
|
||||
0 0 0 91 31 21 211 179 117 208 170 99 243 238 185 173 92 60
|
||||
154 14 11 183 19 13 150 16 12 95 4 6 114 7 7 122 8 8
|
||||
131 10 10 138 12 11 142 13 12
|
||||
135 17 11 144 16 12 145 11 11 167 52 24 159 30 14 150 16 12
|
||||
175 97 50 243 238 185 217 193 123 192 140 79 203 150 89 97 69 52
|
||||
0 0 0 131 94 71 162 137 108 162 137 108 162 137 108 162 137 108
|
||||
162 137 108 97 69 52 97 69 52 97 69 52 97 69 52 91 31 21
|
||||
0 0 0 78 2 7 99 1 11 176 17 11 183 19 13 183 19 13
|
||||
176 17 11 183 19 13 183 19 13 125 8 10 78 2 7 0 0 0
|
||||
78 2 7 0 0 0 97 69 52 97 69 52 97 69 52 131 94 71
|
||||
162 137 108 162 137 108 162 137 108 162 137 108 131 94 71 0 0 0
|
||||
97 69 52 199 143 96 192 140 79 217 193 123 254 255 210 173 92 60
|
||||
183 19 13 176 24 12 114 7 7 117 6 7 119 5 9 131 9 10
|
||||
138 12 11 138 12 11 164 16 11
|
||||
138 15 12 147 12 10 137 11 10 213 153 88 167 52 24 176 24 12
|
||||
167 52 24 243 238 185 238 229 170 203 150 89 176 17 11 176 108 61
|
||||
162 115 76 91 31 21 0 0 0 97 69 52 162 137 108 97 69 52
|
||||
97 69 52 97 69 52 131 94 71 163 121 81 91 31 21 0 0 0
|
||||
183 19 13 77 0 3 0 0 0 78 2 7 119 5 9 168 18 14
|
||||
183 19 13 131 9 10 99 1 11 78 2 7 0 0 0 176 17 11
|
||||
111 14 13 0 0 0 147 67 48 151 106 70 131 94 71 97 69 52
|
||||
0 0 0 162 137 108 97 69 52 0 0 0 0 0 0 143 100 73
|
||||
213 153 88 176 24 12 179 118 76 238 229 170 252 252 206 175 97 50
|
||||
183 19 13 175 97 50 154 43 26 116 3 5 131 10 9 138 12 11
|
||||
138 12 11 156 15 13 176 17 11
|
||||
145 11 11 137 13 11 131 9 10 175 97 50 167 52 24 161 18 12
|
||||
176 24 12 231 215 150 249 249 214 219 195 113 183 19 13 167 52 24
|
||||
175 97 50 179 118 76 163 121 81 97 69 52 0 0 0 0 0 0
|
||||
191 130 98 193 134 84 167 52 24 171 21 16 77 0 3 138 37 20
|
||||
183 19 13 154 14 11 0 0 0 0 0 0 0 0 0 78 2 7
|
||||
78 2 7 0 0 0 0 0 0 0 0 0 120 0 3 183 19 13
|
||||
176 24 12 0 0 0 105 1 7 183 19 13 173 92 60 213 153 88
|
||||
78 2 7 0 0 0 97 69 52 158 125 90 191 130 98 175 97 50
|
||||
163 56 28 183 19 13 213 153 88 250 251 219 241 232 158 167 52 24
|
||||
154 14 11 213 153 88 167 52 24 127 5 8 141 14 11 139 13 11
|
||||
146 12 11 183 19 13 154 14 11
|
||||
137 13 11 131 14 12 131 12 12 159 30 14 174 18 12 167 21 14
|
||||
154 14 11 192 140 79 249 243 164 235 226 137 213 153 88 183 19 13
|
||||
167 21 14 92 0 2 179 118 76 162 137 108 91 31 21 104 58 46
|
||||
77 0 3 77 0 3 0 0 0 0 0 0 0 0 0 119 34 17
|
||||
175 97 50 183 19 13 176 17 11 109 5 7 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 89 3 6 164 16 11 164 16 11 167 52 24
|
||||
138 37 20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
91 31 21 111 35 21 131 94 71 199 143 96 107 0 4 135 17 11
|
||||
183 19 13 183 19 13 216 189 107 249 243 164 213 153 88 147 12 10
|
||||
142 10 9 167 52 24 167 21 14 142 10 9 146 12 11 142 13 12
|
||||
176 17 11 164 16 11 164 16 11
|
||||
124 14 13 128 14 13 143 19 14 154 14 11 163 56 28 176 108 61
|
||||
147 12 10 151 28 16 216 189 107 237 223 121 213 153 88 183 19 13
|
||||
183 19 13 183 19 13 162 137 108 0 0 0 183 19 13 111 14 13
|
||||
91 31 21 158 125 90 131 94 71 97 69 52 0 0 0 78 2 7
|
||||
213 153 88 175 97 50 183 19 13 183 19 13 176 17 11 154 14 11
|
||||
154 14 11 176 17 11 183 19 13 176 17 11 175 97 50 213 153 88
|
||||
119 59 34 0 0 0 0 0 0 97 69 52 162 137 108 97 69 52
|
||||
78 2 7 183 19 13 77 0 3 158 125 90 173 92 60 176 17 11
|
||||
183 19 13 213 153 88 216 189 107 216 189 107 138 37 20 123 0 2
|
||||
176 108 61 167 52 24 142 10 9 150 16 12 144 14 14 164 16 11
|
||||
164 16 11 156 15 13 164 16 11
|
||||
124 14 13 128 14 13 157 23 16 154 14 11 199 143 96 232 217 158
|
||||
176 24 12 139 9 7 163 56 28 213 153 88 216 189 107 213 153 88
|
||||
183 19 13 199 143 96 0 0 0 183 19 13 176 17 11 0 0 0
|
||||
202 183 123 97 69 52 91 31 21 162 115 76 105 45 32 158 83 45
|
||||
213 153 88 192 140 79 175 97 50 175 97 50 183 19 13 183 19 13
|
||||
176 17 11 183 19 13 183 19 13 175 97 50 176 108 61 174 128 69
|
||||
175 97 50 77 0 3 163 56 28 97 69 52 0 0 0 202 183 123
|
||||
97 69 52 111 0 3 183 19 13 0 0 0 191 130 98 183 19 13
|
||||
183 19 13 213 153 88 213 153 88 163 56 28 102 0 4 154 63 38
|
||||
252 252 206 167 52 24 147 12 10 150 16 12 164 16 11 174 18 12
|
||||
152 14 13 161 18 12 156 15 13
|
||||
122 13 12 151 28 16 151 28 16 176 24 12 167 52 24 199 163 109
|
||||
167 52 24 159 30 14 123 0 2 135 17 11 175 97 50 213 153 88
|
||||
183 19 13 193 134 84 0 0 0 176 17 11 0 0 0 162 137 108
|
||||
97 69 52 131 94 71 213 153 88 171 21 16 0 0 0 91 31 21
|
||||
91 31 21 213 153 88 216 189 107 213 153 88 175 97 50 167 52 24
|
||||
167 52 24 175 97 50 213 153 88 213 153 88 237 223 121 129 78 48
|
||||
0 0 0 0 0 0 87 1 5 175 96 57 191 130 98 91 31 21
|
||||
162 137 108 0 0 0 154 14 11 87 1 5 131 94 71 183 19 13
|
||||
175 97 50 175 97 50 139 27 18 111 0 3 131 14 12 173 92 60
|
||||
199 143 96 161 18 12 147 12 10 154 14 11 176 17 11 154 14 11
|
||||
156 15 13 161 18 12 156 15 13
|
||||
139 27 18 138 37 20 154 43 26 169 21 14 159 30 14 159 30 14
|
||||
193 134 84 167 52 24 150 53 31 158 83 45 107 0 4 183 19 13
|
||||
183 19 13 179 118 76 0 0 0 0 0 0 97 69 52 191 177 112
|
||||
0 0 0 183 19 13 87 1 5 0 0 0 0 0 0 0 0 0
|
||||
91 31 21 216 189 107 146 87 48 237 223 121 213 153 88 213 153 88
|
||||
213 153 88 213 153 88 237 223 121 174 128 69 174 128 69 174 128 69
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 183 19 13 78 2 7
|
||||
131 94 71 162 137 108 0 0 0 0 0 0 143 100 73 175 97 50
|
||||
183 19 13 123 0 2 150 53 31 150 53 31 150 53 31 191 130 98
|
||||
133 0 5 147 12 10 147 12 10 176 17 11 164 16 11 156 15 13
|
||||
164 16 11 161 18 12 156 15 13
|
||||
138 37 20 152 48 27 159 29 16 151 28 16 147 24 15 163 56 28
|
||||
215 186 121 175 96 57 164 16 11 199 143 96 173 92 60 164 16 11
|
||||
183 19 13 131 94 71 77 0 3 97 69 52 208 170 99 97 69 52
|
||||
106 0 7 0 0 0 97 69 52 162 137 108 0 0 0 0 0 0
|
||||
105 45 32 124 72 43 146 87 48 237 223 121 237 223 121 237 223 121
|
||||
216 189 107 237 223 121 237 223 121 216 189 107 97 69 52 146 87 48
|
||||
0 0 0 0 0 0 131 94 71 162 137 108 0 0 0 123 0 2
|
||||
78 2 7 206 199 148 131 94 71 77 0 3 97 69 52 175 96 57
|
||||
183 19 13 150 55 28 207 156 97 133 0 5 154 63 38 225 212 158
|
||||
133 0 5 141 15 12 176 17 11 176 17 11 156 15 13 164 16 11
|
||||
176 17 11 161 18 12 156 15 13
|
||||
123 39 27 154 43 26 151 28 16 135 17 11 150 55 28 159 30 14
|
||||
225 212 158 225 212 158 176 24 12 142 10 9 213 153 88 183 19 13
|
||||
183 19 13 97 69 52 78 2 7 151 106 70 162 115 76 91 31 21
|
||||
183 19 13 91 31 21 206 199 148 158 125 90 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 91 31 21 129 78 48 213 153 88 216 189 107
|
||||
216 189 107 216 189 107 174 128 69 120 74 50 91 31 21 91 31 21
|
||||
0 0 0 0 0 0 0 0 0 243 238 185 97 69 52 176 17 11
|
||||
133 0 5 97 69 52 179 118 76 91 31 21 91 31 21 176 111 73
|
||||
183 19 13 213 153 88 167 52 24 159 29 16 225 212 158 225 212 158
|
||||
133 0 5 147 12 10 176 17 11 156 15 13 164 16 11 174 18 12
|
||||
183 19 13 164 16 11 144 14 14
|
||||
150 53 31 139 27 18 128 26 15 119 34 17 141 65 38 133 0 5
|
||||
199 163 109 254 255 240 247 246 193 191 130 98 167 52 24 213 153 88
|
||||
183 19 13 97 69 52 91 31 21 158 83 45 131 94 71 99 1 11
|
||||
111 0 3 97 69 52 158 125 90 97 69 52 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
91 31 21 0 0 0 0 0 0 0 0 0 131 94 71 91 31 21
|
||||
0 0 0 0 0 0 0 0 0 162 137 108 131 94 71 77 0 3
|
||||
120 0 3 97 69 52 163 56 28 91 31 21 91 31 21 173 92 60
|
||||
175 97 50 175 97 50 211 179 117 249 249 214 254 255 240 199 163 109
|
||||
139 9 7 164 16 11 164 16 11 164 16 11 174 18 12 183 19 13
|
||||
183 19 13 154 14 11 145 15 12
|
||||
139 27 18 137 32 21 125 28 16 158 83 45 127 13 12 119 9 8
|
||||
154 43 26 238 229 170 254 255 240 254 255 233 193 134 84 213 153 88
|
||||
213 153 88 131 94 71 97 69 52 193 134 84 182 147 96 0 0 0
|
||||
0 0 0 158 125 90 158 125 90 97 69 52 175 97 50 78 2 7
|
||||
0 0 0 0 0 0 97 69 52 97 69 52 91 31 21 91 31 21
|
||||
97 69 52 97 69 52 97 69 52 146 87 48 237 235 180 187 145 96
|
||||
78 2 7 158 83 45 116 46 29 131 94 71 131 94 71 97 69 52
|
||||
0 0 0 97 69 52 154 43 26 111 35 21 0 0 0 175 96 57
|
||||
213 153 88 213 153 88 254 255 233 254 255 233 238 229 170 151 28 16
|
||||
139 9 7 154 14 11 156 15 13 174 18 12 176 17 11 183 19 13
|
||||
176 17 11 142 13 12 152 14 13
|
||||
138 37 20 119 9 8 158 83 45 138 37 20 122 8 8 125 28 16
|
||||
151 28 16 159 30 14 225 212 158 254 255 233 244 241 169 182 147 96
|
||||
143 100 73 97 69 52 91 31 21 131 94 71 97 69 52 77 0 3
|
||||
78 2 7 158 125 90 131 94 71 0 0 0 119 59 34 97 69 52
|
||||
0 0 0 97 69 52 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 78 2 7 199 143 96 254 255 240 225 212 158
|
||||
174 110 60 216 189 107 150 55 28 97 69 52 143 100 73 131 94 71
|
||||
77 0 3 97 69 52 213 153 88 124 72 43 97 69 52 175 97 50
|
||||
213 153 88 235 226 137 254 255 240 225 212 158 147 12 10 167 52 24
|
||||
147 20 17 147 12 10 164 16 11 168 18 14 183 19 13 176 17 11
|
||||
134 12 11 146 12 11 152 14 13
|
||||
122 13 12 150 55 28 154 63 38 139 9 7 128 8 8 158 83 45
|
||||
176 111 73 139 9 7 175 97 50 249 249 214 252 252 206 97 69 52
|
||||
0 0 0 119 59 34 119 59 34 119 59 34 119 59 34 91 31 21
|
||||
0 0 0 0 0 0 91 31 21 97 69 52 91 31 21 91 31 21
|
||||
0 0 0 0 0 0 97 69 52 249 249 214 249 249 214 237 235 180
|
||||
237 235 180 249 249 214 162 137 108 158 125 90 254 255 240 143 100 73
|
||||
119 59 34 175 97 50 114 7 7 97 69 52 187 167 103 97 69 52
|
||||
80 0 2 91 31 21 131 94 71 91 31 21 169 133 98 183 19 13
|
||||
213 153 88 249 243 164 253 255 226 154 63 38 154 14 11 176 111 73
|
||||
173 92 60 164 16 11 168 18 14 164 16 11 156 15 13 137 13 11
|
||||
144 14 14 145 15 12 150 16 12
|
||||
125 28 16 141 65 38 134 12 11 156 15 13 154 14 11 199 143 96
|
||||
199 143 96 176 24 12 167 52 24 238 229 170 247 246 193 97 69 52
|
||||
174 128 69 237 223 121 237 223 121 237 223 121 237 223 121 216 189 107
|
||||
78 2 7 129 78 48 237 223 121 237 223 121 237 223 121 237 223 121
|
||||
237 223 121 91 31 21 91 31 21 254 255 240 254 255 240 254 255 240
|
||||
254 255 240 254 255 240 206 199 148 0 0 0 131 94 71 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 91 31 21 0 0 0 97 69 52 213 153 88
|
||||
213 153 88 249 243 164 243 238 185 159 29 16 164 16 11 191 130 98
|
||||
199 163 109 164 16 11 167 21 14 161 18 12 150 16 12 150 16 12
|
||||
145 15 12 145 15 12 150 16 12
|
||||
158 83 45 122 13 12 139 9 7 164 16 11 161 18 12 202 183 123
|
||||
237 235 180 167 52 24 175 97 50 247 246 193 249 243 164 97 69 52
|
||||
175 97 50 216 189 107 174 128 69 174 110 60 213 153 88 216 189 107
|
||||
146 87 48 119 59 34 216 189 107 213 153 88 192 140 79 213 153 88
|
||||
237 223 121 192 140 79 97 69 52 254 255 240 237 235 180 97 69 52
|
||||
97 69 52 131 94 71 97 69 52 158 125 90 206 199 148 97 69 52
|
||||
162 137 108 254 255 233 97 69 52 162 137 108 254 255 233 0 0 0
|
||||
97 69 52 249 249 214 254 255 240 254 255 233 97 69 52 97 69 52
|
||||
237 223 121 249 243 164 252 252 206 163 56 28 147 12 10 225 212 158
|
||||
206 199 148 176 17 11 168 22 16 157 19 14 152 17 12 150 16 12
|
||||
145 15 12 144 14 14 144 14 14
|
||||
122 13 12 128 8 8 147 12 10 160 21 14 132 32 17 199 163 109
|
||||
254 255 240 231 215 150 232 217 158 250 251 219 249 243 164 97 69 52
|
||||
175 97 50 216 189 107 91 31 21 0 0 0 119 59 34 216 189 107
|
||||
146 87 48 119 59 34 216 189 107 175 97 50 0 0 0 0 0 0
|
||||
213 153 88 213 153 88 97 69 52 254 255 240 225 212 158 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 206 199 148 254 255 240 97 69 52
|
||||
162 137 108 254 255 240 206 199 148 254 255 240 252 253 227 97 69 52
|
||||
249 249 214 254 255 240 243 238 185 254 255 240 254 255 240 97 69 52
|
||||
187 167 103 249 243 164 254 255 223 238 229 170 206 199 148 254 255 240
|
||||
211 179 117 176 17 11 168 22 16 156 15 13 152 17 12 150 16 12
|
||||
144 14 14 144 14 14 144 14 14
|
||||
114 7 7 137 11 10 156 15 13 125 28 16 138 37 20 193 134 84
|
||||
254 255 233 252 253 227 252 253 227 238 229 170 249 243 164 97 69 52
|
||||
158 83 45 213 153 88 146 87 48 105 45 32 174 128 69 213 153 88
|
||||
91 31 21 119 59 34 213 153 88 146 87 48 0 0 0 0 0 0
|
||||
213 153 88 213 153 88 97 69 52 254 255 240 249 249 214 206 199 148
|
||||
206 199 148 225 212 158 0 0 0 162 137 108 254 255 240 97 69 52
|
||||
162 137 108 254 255 240 254 255 240 162 137 108 97 69 52 162 137 108
|
||||
254 255 240 162 137 108 0 0 0 97 69 52 254 255 240 162 137 108
|
||||
97 69 52 252 252 206 238 229 170 254 255 223 254 255 233 254 255 233
|
||||
199 143 96 176 24 12 167 21 14 156 15 13 151 18 14 144 14 14
|
||||
144 14 14 144 14 14 144 14 14
|
||||
122 8 8 156 15 13 122 13 12 111 14 13 138 37 20 175 97 50
|
||||
249 249 214 254 255 223 247 246 193 219 195 113 249 243 164 97 69 52
|
||||
158 83 45 213 153 88 213 153 88 213 153 88 213 153 88 175 97 50
|
||||
0 0 0 119 59 34 213 153 88 175 97 50 119 59 34 175 97 50
|
||||
213 153 88 175 97 50 97 69 52 254 255 233 254 255 233 254 255 240
|
||||
254 255 240 254 255 240 91 31 21 162 137 108 254 255 240 97 69 52
|
||||
162 137 108 254 255 240 206 199 148 0 0 0 0 0 0 162 137 108
|
||||
254 255 240 191 177 112 131 94 71 162 137 108 254 255 233 206 199 148
|
||||
97 69 52 252 252 206 237 223 121 247 246 193 254 255 223 249 249 214
|
||||
167 52 24 176 24 12 162 20 14 152 14 13 145 15 12 145 15 12
|
||||
144 14 14 141 15 12 144 14 14
|
||||
152 14 13 137 11 10 89 3 6 106 7 8 138 37 20 152 17 12
|
||||
213 153 88 253 255 226 249 249 214 216 189 107 249 243 164 97 69 52
|
||||
163 56 28 213 153 88 175 97 50 141 65 38 175 97 50 213 153 88
|
||||
175 97 50 119 59 34 213 153 88 213 153 88 213 153 88 213 153 88
|
||||
213 153 88 91 31 21 91 31 21 254 255 240 249 249 214 162 137 108
|
||||
162 137 108 162 137 108 0 0 0 202 183 123 254 255 240 97 69 52
|
||||
162 137 108 254 255 240 131 94 71 146 87 48 133 82 52 162 137 108
|
||||
254 255 240 254 255 240 254 255 240 254 255 240 254 255 240 206 199 148
|
||||
97 69 52 249 243 164 216 189 107 250 251 219 254 255 233 207 156 97
|
||||
154 14 11 159 29 16 152 17 12 150 16 12 145 15 12 141 15 12
|
||||
141 15 12 141 15 12 142 13 12
|
||||
147 12 10 95 4 6 95 4 6 119 34 17 135 17 11 141 15 12
|
||||
119 34 17 216 189 107 252 252 206 216 189 107 237 223 121 97 69 52
|
||||
159 30 14 175 97 50 78 2 7 0 0 0 0 0 0 175 97 50
|
||||
167 52 24 150 55 28 175 97 50 167 52 24 138 37 20 132 32 17
|
||||
77 0 3 0 0 0 97 69 52 254 255 240 206 199 148 0 0 0
|
||||
91 31 21 0 0 0 0 0 0 162 137 108 254 255 240 97 69 52
|
||||
162 137 108 254 255 240 97 69 52 151 106 70 120 74 50 162 137 108
|
||||
254 255 240 162 137 108 0 0 0 0 0 0 91 31 21 0 0 0
|
||||
131 94 71 237 223 121 216 189 107 252 252 206 216 189 107 151 28 16
|
||||
144 16 12 151 18 14 150 16 12 145 15 12 144 16 12 141 15 12
|
||||
138 15 12 138 15 12 141 15 12
|
||||
106 7 8 93 4 6 111 35 21 132 32 17 154 14 11 119 34 17
|
||||
111 14 13 167 52 24 213 153 88 216 189 107 213 153 88 97 69 52
|
||||
154 14 11 183 19 13 114 7 7 78 2 7 128 14 13 183 19 13
|
||||
183 19 13 131 14 12 183 19 13 133 0 5 0 0 0 97 69 52
|
||||
131 94 71 158 125 90 97 69 52 249 249 214 191 177 112 97 69 52
|
||||
97 69 52 0 0 0 0 0 0 162 137 108 254 255 240 97 69 52
|
||||
162 137 108 252 253 227 97 69 52 120 74 50 131 94 71 97 69 52
|
||||
250 251 219 237 235 180 97 69 52 97 69 52 162 137 108 91 31 21
|
||||
133 82 52 213 153 88 216 189 107 213 153 88 138 37 20 116 3 5
|
||||
137 13 11 143 13 11 145 15 12 144 16 12 144 16 12 144 14 14
|
||||
138 15 12 138 15 12 138 15 12
|
||||
89 3 6 106 7 8 138 37 20 164 16 11 138 37 20 128 26 15
|
||||
159 30 14 139 9 7 167 52 24 175 97 50 213 153 88 97 69 52
|
||||
164 16 11 183 19 13 183 19 13 183 19 13 183 19 13 183 19 13
|
||||
152 17 12 106 7 8 183 19 13 139 9 7 131 94 71 175 96 57
|
||||
176 24 12 163 56 28 97 69 52 254 255 233 206 199 148 97 69 52
|
||||
213 153 88 213 153 88 119 59 34 162 137 108 254 255 240 97 69 52
|
||||
162 137 108 254 255 240 131 94 71 97 69 52 120 74 50 97 69 52
|
||||
162 137 108 254 255 240 252 253 227 250 251 219 254 255 240 162 137 108
|
||||
97 69 52 213 153 88 175 97 50 111 14 13 95 4 6 119 9 8
|
||||
131 10 9 142 13 12 144 14 14 144 14 14 144 14 14 141 15 12
|
||||
138 15 12 138 15 12 138 15 12
|
||||
93 4 6 123 39 27 164 16 11 167 52 24 138 37 20 176 24 12
|
||||
167 21 14 159 30 14 164 16 11 123 0 2 158 83 45 97 69 52
|
||||
123 0 2 183 19 13 183 19 13 183 19 13 183 19 13 133 0 5
|
||||
0 0 0 78 2 7 183 19 13 107 0 4 97 69 52 111 14 13
|
||||
183 19 13 175 97 50 97 69 52 206 199 148 131 94 71 97 69 52
|
||||
216 189 107 216 189 107 119 59 34 131 94 71 237 235 180 97 69 52
|
||||
162 137 108 225 212 158 97 69 52 97 69 52 93 4 6 158 125 90
|
||||
0 0 0 131 94 71 206 199 148 206 199 148 131 94 71 91 31 21
|
||||
143 100 73 128 26 15 111 14 13 99 0 3 137 32 21 122 8 8
|
||||
129 12 11 138 12 11 142 13 12 141 15 12 141 15 12 138 15 12
|
||||
138 15 12 138 15 12 138 15 12
|
||||
120 41 26 151 28 16 183 19 13 141 65 38 183 19 13 183 19 13
|
||||
183 19 13 193 134 84 154 63 38 77 0 3 169 133 98 131 94 71
|
||||
0 0 0 0 0 0 0 0 0 91 31 21 0 0 0 97 69 52
|
||||
162 137 108 91 31 21 91 31 21 91 31 21 162 137 108 0 0 0
|
||||
183 19 13 192 140 79 97 69 52 91 31 21 0 0 0 131 94 71
|
||||
213 153 88 213 153 88 146 87 48 0 0 0 91 31 21 91 31 21
|
||||
0 0 0 0 0 0 97 69 52 158 125 90 111 0 3 111 14 13
|
||||
193 134 84 97 69 52 0 0 0 0 0 0 91 31 21 174 128 69
|
||||
192 140 79 162 137 108 119 34 17 148 61 42 179 118 76 123 0 2
|
||||
131 14 12 137 13 11 138 15 12 138 15 12 138 15 12 138 15 12
|
||||
134 12 11 134 12 11 137 13 11
|
||||
124 33 21 176 17 11 141 65 38 167 52 24 183 19 13 183 19 13
|
||||
183 19 13 219 195 113 146 90 61 105 45 32 143 100 73 215 186 121
|
||||
211 179 117 193 134 84 179 118 76 193 134 84 169 133 98 146 90 61
|
||||
173 92 60 158 125 90 143 100 73 131 94 71 162 137 108 131 94 71
|
||||
77 0 3 167 52 24 176 108 61 175 97 50 175 97 50 175 97 50
|
||||
213 153 88 213 153 88 192 140 79 175 97 50 176 108 61 120 74 50
|
||||
91 31 21 162 137 108 131 94 71 141 65 38 133 0 5 164 16 11
|
||||
139 9 7 158 83 45 169 113 67 174 110 60 176 108 61 174 128 69
|
||||
221 205 133 169 133 98 137 32 21 191 130 98 211 173 103 123 0 2
|
||||
138 15 12 137 13 11 138 15 12 141 15 12 141 15 12 138 15 12
|
||||
131 14 12 131 14 12 134 12 11
|
||||
154 14 11 163 56 28 116 46 29 183 19 13 183 19 13 183 19 13
|
||||
183 19 13 216 189 107 150 55 28 129 68 42 202 183 123 199 163 109
|
||||
187 167 103 146 90 61 152 17 12 144 16 12 139 9 7 92 0 2
|
||||
92 0 2 99 0 3 93 4 6 0 0 0 0 0 0 162 137 108
|
||||
97 69 52 0 0 0 78 2 7 78 2 7 77 0 3 167 52 24
|
||||
213 153 88 213 153 88 175 97 50 127 5 8 0 0 0 0 0 0
|
||||
162 137 108 91 31 21 77 0 3 147 24 15 183 19 13 183 19 13
|
||||
154 14 11 152 17 12 164 16 11 154 14 11 158 83 45 191 177 112
|
||||
225 212 158 206 199 148 154 43 26 175 97 50 175 97 50 133 0 5
|
||||
137 13 11 138 15 12 138 15 12 138 15 12 138 15 12 138 15 12
|
||||
131 14 12 138 15 12 134 12 11
|
||||
176 24 12 123 39 27 183 19 13 183 19 13 183 19 13 183 19 13
|
||||
158 83 45 175 97 50 152 48 27 95 4 6 237 235 180 232 217 158
|
||||
199 163 109 182 147 96 174 128 69 175 97 50 175 97 50 167 52 24
|
||||
176 17 11 164 16 11 167 52 24 158 83 45 99 0 3 77 0 3
|
||||
162 137 108 131 94 71 0 0 0 0 0 0 0 0 0 111 35 21
|
||||
158 83 45 158 83 45 91 31 21 0 0 0 91 31 21 191 177 112
|
||||
91 31 21 77 0 3 151 28 16 213 153 88 183 19 13 183 19 13
|
||||
183 19 13 175 97 50 175 97 50 192 140 79 187 167 103 221 205 133
|
||||
254 255 210 237 235 180 139 9 7 176 24 12 183 19 13 137 11 10
|
||||
137 13 11 138 15 12 138 15 12 138 15 12 138 15 12 134 12 11
|
||||
131 14 12 134 12 11 131 12 12
|
||||
154 43 26 156 20 14 183 19 13 183 19 13 183 19 13 175 97 50
|
||||
78 2 7 119 9 8 224 209 127 136 76 50 140 85 58 249 249 214
|
||||
232 217 158 206 199 148 195 174 110 213 153 88 208 170 99 175 97 50
|
||||
183 19 13 183 19 13 183 19 13 213 153 88 127 5 8 116 3 5
|
||||
77 0 3 158 125 90 162 137 108 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 131 94 71 162 137 108 91 31 21
|
||||
92 0 2 133 0 5 175 97 50 213 153 88 183 19 13 183 19 13
|
||||
183 19 13 213 153 88 216 189 107 216 189 107 221 205 133 247 246 193
|
||||
253 255 226 158 83 45 154 63 38 213 153 88 183 19 13 134 12 11
|
||||
137 13 11 137 13 11 138 15 12 138 15 12 138 15 12 131 14 12
|
||||
131 14 12 131 12 12 131 14 12
|
||||
128 26 15 183 19 13 183 19 13 183 19 13 175 97 50 104 58 46
|
||||
0 0 0 93 4 6 238 229 170 237 235 180 87 1 5 136 76 50
|
||||
202 183 123 202 183 123 225 212 158 232 217 158 235 226 137 213 153 88
|
||||
183 19 13 213 153 88 183 19 13 213 153 88 147 12 10 176 17 11
|
||||
135 17 11 77 0 3 104 58 46 202 183 123 91 31 21 0 0 0
|
||||
97 69 52 0 0 0 162 137 108 131 94 71 77 0 3 111 14 13
|
||||
169 21 14 133 0 5 175 97 50 175 97 50 175 97 50 175 97 50
|
||||
175 97 50 237 223 121 232 217 158 232 217 158 225 212 158 206 199 148
|
||||
158 83 45 120 0 3 232 217 158 237 223 121 139 9 7 134 12 11
|
||||
137 13 11 134 12 11 134 12 11 138 15 12 138 15 12 131 14 12
|
||||
131 14 12 131 14 12 128 14 13
|
||||
138 37 20 183 19 13 183 19 13 175 97 50 146 87 48 0 0 0
|
||||
78 2 7 77 0 3 136 76 50 225 212 158 119 34 17 123 0 2
|
||||
107 0 4 127 13 12 132 32 17 238 229 170 253 254 208 213 153 88
|
||||
213 153 88 213 153 88 183 19 13 175 97 50 183 19 13 183 19 13
|
||||
183 19 13 156 20 14 99 0 3 97 69 52 131 94 71 0 0 0
|
||||
97 69 52 97 69 52 131 94 71 77 0 3 127 13 12 183 19 13
|
||||
164 16 11 183 19 13 213 153 88 183 19 13 213 153 88 213 153 88
|
||||
213 153 88 241 232 158 252 252 206 175 96 57 135 17 11 122 7 7
|
||||
107 0 4 125 28 16 225 212 158 158 83 45 123 0 2 134 12 11
|
||||
137 13 11 137 13 11 134 12 11 138 15 12 131 14 12 128 14 13
|
||||
128 14 13 128 14 13 131 12 12
|
||||
167 52 24 183 19 13 183 19 13 175 97 50 0 0 0 77 0 3
|
||||
78 2 7 78 2 7 87 1 5 119 34 17 143 19 14 114 7 7
|
||||
109 5 7 143 80 49 107 0 4 199 143 96 254 255 240 237 223 121
|
||||
213 153 88 213 153 88 175 97 50 183 19 13 175 97 50 183 19 13
|
||||
183 19 13 175 97 50 176 17 11 109 5 7 162 137 108 97 69 52
|
||||
97 69 52 131 94 71 120 38 28 142 10 9 183 19 13 175 97 50
|
||||
183 19 13 183 19 13 175 97 50 167 52 24 213 153 88 213 153 88
|
||||
216 189 107 254 255 223 238 229 170 139 9 7 143 80 49 125 28 16
|
||||
102 4 5 116 9 9 128 26 15 116 3 5 122 13 12 131 12 12
|
||||
134 12 11 134 12 11 134 12 11 131 14 12 131 14 12 128 14 13
|
||||
128 14 13 128 14 13 128 14 13
|
||||
183 19 13 183 19 13 176 108 61 91 31 21 0 0 0 78 2 7
|
||||
78 2 7 89 3 6 78 2 7 131 10 9 106 7 8 102 4 5
|
||||
147 12 10 158 83 45 123 0 2 179 118 76 254 255 240 247 246 193
|
||||
216 189 107 216 189 107 213 153 88 213 153 88 213 153 88 183 19 13
|
||||
213 153 88 213 153 88 183 19 13 183 19 13 191 130 98 97 69 52
|
||||
0 0 0 169 133 98 183 19 13 183 19 13 175 97 50 213 153 88
|
||||
183 19 13 175 97 50 213 153 88 213 153 88 213 153 88 213 153 88
|
||||
235 226 137 254 255 233 206 199 148 128 8 8 147 67 48 122 13 12
|
||||
111 3 7 117 6 7 109 5 7 106 7 8 122 13 12 131 12 12
|
||||
131 14 12 131 14 12 131 14 12 131 14 12 131 14 12 128 14 13
|
||||
128 14 13 128 14 13 128 14 13
|
||||
183 19 13 175 97 50 119 70 46 0 0 0 77 0 3 78 2 7
|
||||
89 3 6 78 2 7 128 8 8 134 12 11 78 2 7 154 14 11
|
||||
135 17 11 176 111 73 123 0 2 148 61 42 254 255 223 252 253 227
|
||||
249 243 164 237 223 121 216 189 107 216 189 107 213 153 88 183 19 13
|
||||
216 189 107 213 153 88 183 19 13 183 19 13 183 19 13 131 94 71
|
||||
97 69 52 175 96 57 175 97 50 183 19 13 213 153 88 216 189 107
|
||||
183 19 13 175 97 50 216 189 107 213 153 88 216 189 107 237 223 121
|
||||
252 252 206 254 255 233 191 130 98 120 0 3 176 111 73 128 14 13
|
||||
111 3 7 119 9 8 116 9 9 116 9 9 122 13 12 131 12 12
|
||||
131 14 12 131 14 12 131 14 12 128 14 13 128 14 13 128 14 13
|
||||
128 14 13 128 14 13 128 14 13
|
||||
175 97 50 175 97 50 0 0 0 77 0 3 78 2 7 78 2 7
|
||||
89 3 6 114 7 7 183 19 13 78 2 7 154 14 11 160 21 14
|
||||
103 5 5 103 5 5 103 5 5 133 0 5 225 212 158 254 255 240
|
||||
249 249 214 244 241 169 237 223 121 249 243 164 193 134 84 175 97 50
|
||||
237 223 121 216 189 107 213 153 88 175 97 50 183 19 13 169 133 98
|
||||
162 137 108 183 19 13 213 153 88 175 97 50 213 153 88 237 223 121
|
||||
175 97 50 183 19 13 247 246 193 235 226 137 237 223 121 252 252 206
|
||||
254 255 223 250 251 219 163 56 28 116 3 5 116 3 5 118 7 7
|
||||
116 9 9 116 9 9 116 9 9 122 13 12 128 14 13 131 14 12
|
||||
131 14 12 131 14 12 128 14 13 128 14 13 128 14 13 128 14 13
|
||||
124 14 13 124 14 13 128 14 13
|
||||
176 108 61 78 2 7 77 0 3 77 0 3 78 2 7 89 3 6
|
||||
89 3 6 183 19 13 122 13 12 128 6 9 183 19 13 111 14 13
|
||||
111 14 13 106 7 8 117 6 7 139 9 7 175 97 50 249 249 214
|
||||
254 255 240 254 255 233 254 255 240 225 212 158 154 43 26 176 111 73
|
||||
211 179 117 254 255 210 237 223 121 213 153 88 183 19 13 213 153 88
|
||||
199 143 96 175 97 50 237 223 121 213 153 88 167 52 24 237 223 121
|
||||
237 223 121 159 30 14 191 130 98 254 255 240 254 255 240 254 255 240
|
||||
254 255 233 191 130 98 120 0 3 116 9 9 119 5 9 116 3 5
|
||||
116 3 5 116 3 5 119 5 9 125 8 10 125 8 10 127 13 12
|
||||
131 14 12 131 14 12 128 14 13 128 14 13 128 14 13 124 14 13
|
||||
124 14 13 128 14 13 128 14 13
|
||||
91 31 21 0 0 0 77 0 3 78 2 7 89 3 6 78 2 7
|
||||
174 18 12 174 18 12 106 7 8 183 19 13 151 28 16 111 14 13
|
||||
111 14 13 127 5 8 122 7 7 176 24 12 167 52 24 158 83 45
|
||||
191 130 98 202 183 123 179 118 76 122 13 12 120 0 3 191 130 98
|
||||
163 56 28 199 163 109 254 255 210 213 153 88 213 153 88 175 97 50
|
||||
175 97 50 213 153 88 249 243 164 237 223 121 176 17 11 167 52 24
|
||||
249 243 164 176 111 73 92 0 2 147 67 48 199 163 109 199 163 109
|
||||
147 67 48 107 0 4 106 7 8 114 7 7 137 32 21 124 33 21
|
||||
124 33 21 137 32 21 124 33 21 137 32 21 137 32 21 137 32 21
|
||||
131 14 12 131 14 12 128 14 13 128 14 13 127 13 12 124 14 13
|
||||
122 13 12 124 14 13 127 13 12
|
||||
0 0 0 77 0 3 77 0 3 78 2 7 78 2 7 131 14 12
|
||||
183 19 13 91 2 10 183 19 13 183 19 13 125 28 16 125 28 16
|
||||
131 9 10 116 3 5 152 17 12 176 24 12 167 52 24 111 14 13
|
||||
92 0 2 111 14 13 95 4 6 89 3 6 133 0 5 238 229 170
|
||||
191 130 98 139 9 7 249 249 214 211 179 117 175 97 50 213 153 88
|
||||
213 153 88 235 226 137 244 241 169 235 226 137 164 16 11 199 163 109
|
||||
254 255 240 176 111 73 80 0 2 89 3 6 87 1 5 80 0 2
|
||||
80 0 2 89 3 6 102 4 5 116 9 9 148 61 42 136 76 50
|
||||
147 67 48 147 67 48 118 44 32 147 67 48 147 67 48 150 53 31
|
||||
127 13 12 128 14 13 127 13 12 127 13 12 127 13 12 124 14 13
|
||||
124 14 13 122 13 12 122 13 12
|
||||
0 0 0 77 0 3 78 2 7 78 2 7 93 4 6 183 19 13
|
||||
106 7 8 154 14 11 183 19 13 132 32 17 132 32 17 138 15 12
|
||||
127 5 8 144 16 12 183 19 13 176 24 12 111 14 13 78 2 7
|
||||
91 31 21 91 31 21 78 2 7 123 0 2 154 43 26 252 253 227
|
||||
154 63 38 150 53 31 254 255 240 191 130 98 167 52 24 237 223 121
|
||||
235 226 137 247 246 193 254 255 210 215 186 121 158 83 45 254 255 240
|
||||
249 249 214 119 34 17 119 70 46 91 31 21 77 0 3 78 2 7
|
||||
78 2 7 87 1 5 102 4 5 116 9 9 123 39 27 148 61 42
|
||||
125 28 16 125 28 16 125 28 16 123 39 27 148 61 42 148 61 42
|
||||
122 13 12 122 13 12 128 14 13 127 13 12 124 14 13 122 13 12
|
||||
122 13 12 122 13 12 122 13 12
|
||||
0 0 0 77 0 3 78 2 7 78 2 7 183 19 13 143 19 14
|
||||
116 3 5 183 19 13 152 48 27 124 33 21 128 26 15 139 9 7
|
||||
135 17 11 183 19 13 183 19 13 151 28 16 77 0 3 91 31 21
|
||||
91 31 21 77 0 3 105 1 7 133 0 5 103 5 5 249 249 214
|
||||
191 130 98 176 111 73 206 199 148 147 12 10 158 83 45 249 243 164
|
||||
252 252 206 252 252 206 254 255 223 173 92 60 176 111 73 254 255 240
|
||||
173 92 60 92 0 2 78 2 7 77 0 3 77 0 3 77 0 3
|
||||
78 2 7 89 3 6 106 7 8 119 9 8 122 13 12 122 8 8
|
||||
119 5 9 119 9 8 119 9 8 119 9 8 122 13 12 128 14 13
|
||||
127 13 12 127 13 12 127 13 12 124 14 13 124 14 13 122 13 12
|
||||
122 13 12 122 13 12 122 13 12
|
||||
77 0 3 77 0 3 78 2 7 143 13 11 183 19 13 91 2 10
|
||||
183 19 13 167 52 24 119 34 17 125 28 16 145 11 11 122 13 12
|
||||
183 19 13 183 19 13 183 19 13 78 2 7 78 2 7 91 31 21
|
||||
77 0 3 78 2 7 127 5 8 89 3 6 80 0 2 153 103 68
|
||||
179 118 76 111 0 3 119 9 8 122 7 7 173 92 60 254 255 223
|
||||
249 249 214 254 255 223 221 205 133 123 0 2 140 85 58 249 249 214
|
||||
122 8 8 89 3 6 78 2 7 78 2 7 78 2 7 78 2 7
|
||||
87 1 5 95 4 6 114 7 7 122 13 12 125 8 10 122 13 12
|
||||
124 14 13 127 13 12 127 13 12 127 13 12 127 13 12 127 13 12
|
||||
127 13 12 124 14 13 124 14 13 124 14 13 122 13 12 122 13 12
|
||||
122 13 12 122 13 12 122 13 12
|
||||
77 0 3 77 0 3 95 4 6 183 19 13 103 5 5 164 16 11
|
||||
183 19 13 124 33 21 124 33 21 142 10 9 122 8 8 176 24 12
|
||||
183 19 13 183 19 13 128 14 13 78 2 7 105 45 32 78 2 7
|
||||
78 2 7 125 8 10 102 4 5 79 0 3 93 4 6 103 5 5
|
||||
111 14 13 111 14 13 111 14 13 114 7 7 176 111 73 253 255 226
|
||||
250 251 219 249 249 214 167 52 24 119 34 17 118 44 32 162 115 76
|
||||
111 14 13 87 1 5 93 4 6 93 4 6 93 4 6 93 4 6
|
||||
95 4 6 106 7 8 116 9 9 122 13 12 127 13 12 127 13 12
|
||||
128 14 13 128 14 13 127 13 12 128 14 13 128 14 13 128 14 13
|
||||
127 13 12 124 14 13 124 14 13 124 14 13 124 14 13 122 13 12
|
||||
122 13 12 122 13 12 116 9 9
|
||||
77 0 3 77 0 3 183 19 13 142 10 9 119 5 9 183 19 13
|
||||
138 37 20 124 33 21 135 17 11 139 9 7 147 24 15 183 19 13
|
||||
183 19 13 167 52 24 80 0 2 114 50 39 91 31 21 77 0 3
|
||||
131 9 10 128 6 9 87 1 5 93 4 6 95 4 6 103 5 5
|
||||
95 4 6 119 34 17 138 37 20 103 5 5 179 118 76 254 255 233
|
||||
254 255 233 199 163 109 138 37 20 91 31 21 91 31 21 80 0 2
|
||||
89 3 6 93 4 6 102 4 5 106 7 8 106 7 8 106 7 8
|
||||
106 7 8 106 7 8 116 9 9 124 14 13 127 13 12 127 13 12
|
||||
124 14 13 124 14 13 124 14 13 128 14 13 124 14 13 124 14 13
|
||||
124 14 13 124 14 13 124 14 13 122 13 12 122 13 12 122 13 12
|
||||
122 13 12 116 9 9 116 9 9
|
||||
77 0 3 154 14 11 176 17 11 89 3 6 183 19 13 167 52 24
|
||||
124 33 21 124 33 21 145 11 11 128 14 13 183 19 13 183 19 13
|
||||
167 52 24 99 0 3 111 35 21 105 45 32 77 0 3 116 9 9
|
||||
147 12 10 93 4 6 95 4 6 106 7 8 103 5 5 103 5 5
|
||||
92 0 2 119 59 34 148 61 42 106 7 8 179 118 76 254 255 240
|
||||
243 238 185 163 56 28 119 59 34 111 35 21 111 35 21 80 0 2
|
||||
89 3 6 102 4 5 106 7 8 114 7 7 114 7 7 106 7 8
|
||||
116 9 9 116 9 9 122 13 12 124 14 13 127 13 12 122 13 12
|
||||
122 13 12 122 13 12 124 14 13 124 14 13 124 14 13 122 13 12
|
||||
124 14 13 122 13 12 124 14 13 122 13 12 122 13 12 122 13 12
|
||||
122 13 12 122 13 12 122 13 12
|
||||
103 5 5 183 19 13 78 2 7 176 17 11 167 52 24 119 34 17
|
||||
124 33 21 137 11 10 125 8 10 176 24 12 183 19 13 183 19 13
|
||||
129 12 11 91 2 10 119 70 46 78 2 7 106 7 8 176 17 11
|
||||
111 1 9 95 4 6 106 7 8 106 7 8 106 7 8 103 5 5
|
||||
102 4 5 102 4 5 111 14 13 124 33 21 179 118 76 254 255 240
|
||||
176 111 73 119 9 8 95 4 6 141 65 38 141 65 38 80 0 2
|
||||
99 1 11 106 7 8 114 7 7 114 7 7 116 9 9 116 9 9
|
||||
116 9 9 116 9 9 122 13 12 122 13 12 124 14 13 124 14 13
|
||||
122 13 12 122 13 12 122 13 12 122 13 12 122 13 12 122 13 12
|
||||
122 13 12 122 13 12 124 14 13 122 13 12 122 13 12 122 13 12
|
||||
116 9 9 116 9 9 116 9 9
|
||||
183 19 13 106 7 8 133 0 5 183 19 13 138 37 20 125 28 16
|
||||
128 14 13 127 5 8 157 23 16 183 19 13 183 19 13 176 24 12
|
||||
79 0 3 119 70 46 91 31 21 89 3 6 176 17 11 142 10 9
|
||||
91 2 10 114 7 7 114 7 7 114 7 7 109 5 7 106 7 8
|
||||
102 4 5 103 5 5 106 7 8 92 0 2 191 130 98 191 130 98
|
||||
119 9 8 111 14 13 106 7 8 103 5 5 102 4 5 95 4 6
|
||||
106 7 8 109 5 7 114 7 7 116 9 9 116 9 9 119 9 8
|
||||
119 9 8 122 13 12 122 13 12 122 13 12 122 13 12 122 13 12
|
||||
124 14 13 122 13 12 122 13 12 122 13 12 122 13 12 122 13 12
|
||||
122 13 12 122 13 12 122 13 12 122 13 12 122 13 12 122 13 12
|
||||
116 9 9 116 9 9 119 9 8
|
||||
135 17 11 99 1 11 183 19 13 167 52 24 119 34 17 125 28 16
|
||||
147 12 10 131 14 12 183 19 13 183 19 13 183 19 13 87 1 5
|
||||
105 45 32 105 45 32 77 0 3 145 11 11 176 17 11 95 4 6
|
||||
106 7 8 116 9 9 119 9 8 119 9 8 116 9 9 109 5 7
|
||||
106 7 8 106 7 8 102 4 5 106 7 8 124 33 21 103 5 5
|
||||
93 4 6 93 4 6 106 7 8 106 7 8 102 4 5 106 7 8
|
||||
109 5 7 114 7 7 116 9 9 119 9 8 119 9 8 122 13 12
|
||||
122 13 12 119 9 8 119 9 8 119 9 8 122 13 12 122 13 12
|
||||
122 13 12 122 13 12 122 13 12 122 13 12 122 13 12 122 13 12
|
||||
122 13 12 122 13 12 122 13 12 122 13 12 122 13 12 122 13 12
|
||||
116 9 9 116 9 9 119 9 8
|
||||
File diff suppressed because it is too large
Load Diff
12
config/kernel/kernel.config.bpf
Normal file
12
config/kernel/kernel.config.bpf
Normal file
@@ -0,0 +1,12 @@
|
||||
CONFIG_BPF_SYSCALL=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_INFO_BTF=y
|
||||
CONFIG_DEBUG_INFO_DWARF4=y
|
||||
CONFIG_BPF_UNPRIV_DEFAULT_OFF=y
|
||||
CONFIG_KPROBES=y
|
||||
CONFIG_KPROBE_EVENTS=y
|
||||
CONFIG_BPF_EVENTS=y
|
||||
CONFIG_UPROBES=y
|
||||
CONFIG_UPROBE_EVENTS=y
|
||||
CONFIG_DEBUG_FS=y
|
||||
CONFIG_MODULE_SIG_FORCE=n
|
||||
@@ -386,10 +386,10 @@ CONFIG_DMI=y
|
||||
# CONFIG_GART_IOMMU is not set
|
||||
CONFIG_BOOT_VESA_SUPPORT=y
|
||||
# CONFIG_MAXSMP is not set
|
||||
CONFIG_NR_CPUS_RANGE_BEGIN=2
|
||||
CONFIG_NR_CPUS_RANGE_BEGIN=512
|
||||
CONFIG_NR_CPUS_RANGE_END=512
|
||||
CONFIG_NR_CPUS_DEFAULT=64
|
||||
CONFIG_NR_CPUS=64
|
||||
CONFIG_NR_CPUS_DEFAULT=512
|
||||
CONFIG_NR_CPUS=512
|
||||
CONFIG_SCHED_CLUSTER=y
|
||||
CONFIG_SCHED_SMT=y
|
||||
CONFIG_SCHED_MC=y
|
||||
@@ -7050,8 +7050,8 @@ CONFIG_NTFS3_FS_POSIX_ACL=y
|
||||
# Pseudo filesystems
|
||||
#
|
||||
CONFIG_PROC_FS=y
|
||||
# CONFIG_PROC_KCORE is not set
|
||||
# CONFIG_PROC_VMCORE is not set
|
||||
CONFIG_PROC_KCORE=y
|
||||
CONFIG_PROC_VMCORE=y
|
||||
CONFIG_PROC_SYSCTL=y
|
||||
CONFIG_PROC_PAGE_MONITOR=y
|
||||
# CONFIG_PROC_CHILDREN is not set
|
||||
@@ -7759,7 +7759,10 @@ CONFIG_OBJTOOL=y
|
||||
#
|
||||
# Generic Kernel Debugging Instruments
|
||||
#
|
||||
# CONFIG_MAGIC_SYSRQ is not set
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1
|
||||
CONFIG_MAGIC_SYSRQ_SERIAL=y
|
||||
CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE=""
|
||||
# CONFIG_DEBUG_FS is not set
|
||||
CONFIG_HAVE_ARCH_KGDB=y
|
||||
# CONFIG_KGDB is not set
|
||||
@@ -7834,7 +7837,7 @@ CONFIG_PANIC_ON_OOPS_VALUE=0
|
||||
CONFIG_PANIC_TIMEOUT=0
|
||||
CONFIG_LOCKUP_DETECTOR=y
|
||||
CONFIG_SOFTLOCKUP_DETECTOR=y
|
||||
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
|
||||
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
|
||||
CONFIG_HAVE_HARDLOCKUP_DETECTOR_BUDDY=y
|
||||
CONFIG_HARDLOCKUP_DETECTOR=y
|
||||
# CONFIG_HARDLOCKUP_DETECTOR_PREFER_BUDDY is not set
|
||||
@@ -7843,8 +7846,8 @@ CONFIG_HARDLOCKUP_DETECTOR_PERF=y
|
||||
# CONFIG_HARDLOCKUP_DETECTOR_ARCH is not set
|
||||
CONFIG_HARDLOCKUP_DETECTOR_COUNTS_HRTIMER=y
|
||||
CONFIG_HARDLOCKUP_CHECK_TIMESTAMP=y
|
||||
# CONFIG_BOOTPARAM_HARDLOCKUP_PANIC is not set
|
||||
# CONFIG_DETECT_HUNG_TASK is not set
|
||||
CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y
|
||||
CONFIG_DETECT_HUNG_TASK=y
|
||||
# CONFIG_WQ_WATCHDOG is not set
|
||||
# CONFIG_WQ_CPU_INTENSIVE_REPORT is not set
|
||||
# CONFIG_TEST_LOCKUP is not set
|
||||
@@ -8032,3 +8035,16 @@ CONFIG_ARCH_USE_MEMTEST=y
|
||||
#
|
||||
# end of Rust hacking
|
||||
# end of Kernel hacking
|
||||
CONFIG_BPF_SYSCALL=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_INFO_BTF=y
|
||||
CONFIG_DEBUG_INFO_DWARF4=y
|
||||
CONFIG_BPF_UNPRIV_DEFAULT_OFF=y
|
||||
CONFIG_KPROBES=y
|
||||
CONFIG_KPROBE_EVENTS=y
|
||||
CONFIG_BPF_EVENTS=y
|
||||
CONFIG_UPROBES=y
|
||||
CONFIG_UPROBE_EVENTS=y
|
||||
CONFIG_DEBUG_FS=y
|
||||
CONFIG_MODULE_SIG_FORCE=y
|
||||
CONFIG_FPROBE=y
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
'enabled' => 1,
|
||||
'subMenu' => $subproxy
|
||||
};
|
||||
$menu->{'07.ipfire'} = {'caption' => 'IPFire',
|
||||
$menu->{'07.ipfire'} = {'caption' => 'BPFire',
|
||||
'enabled' => 1,
|
||||
'subMenu' => $subipfire
|
||||
};
|
||||
|
||||
@@ -4,6 +4,12 @@
|
||||
'title' => "$Lang::tr{'virtual private networking'}",
|
||||
'enabled' => 1,
|
||||
};
|
||||
$subservices->{'15.wireguard'} = {
|
||||
'caption' => $Lang::tr{'wireguard'},
|
||||
'uri' => '/cgi-bin/wireguard.cgi',
|
||||
'title' => "$Lang::tr{'wireguard'}",
|
||||
'enabled' => 1,
|
||||
};
|
||||
$subservices->{'20.openvpn'} = {
|
||||
'caption' => 'OpenVPN',
|
||||
'uri' => '/cgi-bin/ovpnmain.cgi',
|
||||
|
||||
@@ -26,12 +26,6 @@
|
||||
'title' => "$Lang::tr{'ipblocklist'}",
|
||||
'enabled' => 1,
|
||||
};
|
||||
$subfirewall->{'60.locationblock'} = {
|
||||
'caption' => $Lang::tr{'locationblock'},
|
||||
'uri' => '/cgi-bin/location-block.cgi',
|
||||
'title' => $Lang::tr{'locationblock'},
|
||||
'enabled' => 1,
|
||||
};
|
||||
$subfirewall->{'70.wireless'} = {
|
||||
'caption' => $Lang::tr{'blue access'},
|
||||
'uri' => '/cgi-bin/wireless.cgi',
|
||||
|
||||
@@ -1,8 +1,48 @@
|
||||
$subipfire->{'10.pakfire'} = {'caption' => 'Pakfire',
|
||||
'uri' => '/cgi-bin/pakfire.cgi',
|
||||
'title' => "Pakfire",
|
||||
'enabled' => 1,
|
||||
};
|
||||
$subipfire->{'10.ddos'} = {'caption' => $Lang::tr{'ebpf xdp ddos'},
|
||||
'uri' => '/cgi-bin/ddos.cgi',
|
||||
'title' => "$Lang::tr{'ebpf xdp ddos system'}",
|
||||
'enabled' => 1,
|
||||
};
|
||||
$subipfire->{'15.xdpdns'} = {'caption' => $Lang::tr{'xdpdns domain'},
|
||||
'uri' => '/cgi-bin/xdpdns.cgi',
|
||||
'title' => "$Lang::tr{'xdpdns domain'}",
|
||||
'enabled' => 1,
|
||||
};
|
||||
$subipfire->{'16.xdpsni'} = {'caption' => $Lang::tr{'xdpsni domain'},
|
||||
'uri' => '/cgi-bin/xdpsni.cgi',
|
||||
'title' => "$Lang::tr{'xdpsni domain'}",
|
||||
'enabled' => 1,
|
||||
};
|
||||
$subipfire->{'17.locationblock'} = {
|
||||
'caption' => $Lang::tr{'locationblock'},
|
||||
'uri' => '/cgi-bin/location-block.cgi',
|
||||
'title' => $Lang::tr{'locationblock'},
|
||||
'enabled' => 1,
|
||||
};
|
||||
$subipfire->{'20.loxilb'} = {
|
||||
'caption' => $Lang::tr{'loxilb enable'},
|
||||
'uri' => '/cgi-bin/loxilb.cgi',
|
||||
'title' => "$Lang::tr{'loxilb enable'}",
|
||||
'enabled' => 1,
|
||||
};
|
||||
$subipfire->{'30.loxilbconfig'} = {
|
||||
'caption' => $Lang::tr{'loxilb config'},
|
||||
'uri' => '/cgi-bin/loxilbconfig.cgi',
|
||||
'title' => "$Lang::tr{'loxilb config'}",
|
||||
'enabled' => 1,
|
||||
};
|
||||
$subipfire->{'40.loxilbfw'} = {
|
||||
'caption' => $Lang::tr{'loxilb fw'},
|
||||
'uri' => '/cgi-bin/loxilbfw.cgi',
|
||||
'title' => "$Lang::tr{'loxilb fw'}",
|
||||
'enabled' => 1,
|
||||
};
|
||||
$subipfire->{'50.keepalived'} = {
|
||||
'caption' => $Lang::tr{'keepalived'},
|
||||
'uri' => '/cgi-bin/keepalived.cgi',
|
||||
'title' => "$Lang::tr{'keepalived'}",
|
||||
'enabled' => 1,
|
||||
};
|
||||
$subipfire->{'99.help'} = {'caption' => $Lang::tr{'help'},
|
||||
'uri' => '/cgi-bin/help.cgi',
|
||||
'title' => "$Lang::tr{'help'}",
|
||||
|
||||
@@ -8,6 +8,21 @@
|
||||
'title' => "$Lang::tr{'log settings'}",
|
||||
'enabled' => 1
|
||||
};
|
||||
$sublogs->{'21.xdpdns'} = {'caption' => $Lang::tr{'xdpdns log'},
|
||||
'uri' => '/cgi-bin/logs.cgi/xdpdnslog.dat',
|
||||
'title' => "$Lang::tr{'xdpdns log'}",
|
||||
'enabled' => 1
|
||||
};
|
||||
$sublogs->{'22.xdpsni'} = {'caption' => $Lang::tr{'xdpsni log'},
|
||||
'uri' => '/cgi-bin/logs.cgi/xdpsnilog.dat',
|
||||
'title' => "$Lang::tr{'xdpsni log'}",
|
||||
'enabled' => 1
|
||||
};
|
||||
$sublogs->{'23.wireguard'} = {'caption' => $Lang::tr{'wg log'},
|
||||
'uri' => '/cgi-bin/logs.cgi/wireguardlog.dat',
|
||||
'title' => "$Lang::tr{'wg log'}",
|
||||
'enabled' => 1
|
||||
};
|
||||
$sublogs->{'30.proxy'} = {'caption' => $Lang::tr{'proxy logs'},
|
||||
'uri' => '/cgi-bin/logs.cgi/proxylog.dat',
|
||||
'title' => "$Lang::tr{'proxy logs'}",
|
||||
|
||||
@@ -92,6 +92,7 @@ etc/rc.d/init.d/unbound
|
||||
etc/rc.d/init.d/vnstat
|
||||
etc/rc.d/init.d/waitdrives
|
||||
etc/rc.d/init.d/wlanclient
|
||||
etc/rc.d/init.d/ddos
|
||||
#etc/rc.d/rc0.d
|
||||
#etc/rc.d/rc0.d/K01imspetor
|
||||
#etc/rc.d/rc0.d/K01motion
|
||||
|
||||
8
config/rootfiles/common/arpwatch
Normal file
8
config/rootfiles/common/arpwatch
Normal file
@@ -0,0 +1,8 @@
|
||||
etc/rc.d/init.d/arpwatch
|
||||
etc/sysconfig/arpwatch
|
||||
usr/sbin/arpsnmp
|
||||
usr/sbin/arpwatch
|
||||
#usr/share/man/man8/arpsnmp.8
|
||||
#usr/share/man/man8/arpwatch.8
|
||||
#var/lib/arpwatch
|
||||
var/lib/arpwatch/ethercodes.dat
|
||||
2
config/rootfiles/common/bpftool
Normal file
2
config/rootfiles/common/bpftool
Normal file
@@ -0,0 +1,2 @@
|
||||
usr/sbin/bpftool
|
||||
usr/share/bash-completion/completions/bpftool
|
||||
@@ -98,6 +98,7 @@ var/ipfire/langs
|
||||
#var/ipfire/langs/pl.pl
|
||||
#var/ipfire/langs/ru.pl
|
||||
#var/ipfire/langs/tr.pl
|
||||
#var/ipfire/langs/zh.pl
|
||||
var/ipfire/logging
|
||||
#var/ipfire/logging/settings
|
||||
var/ipfire/mac
|
||||
@@ -196,6 +197,14 @@ var/ipfire/vpn
|
||||
#var/ipfire/vpn/settings
|
||||
var/ipfire/wakeonlan
|
||||
#var/ipfire/wakeonlan/clients.conf
|
||||
var/ipfire/wireguard
|
||||
#var/ipfire/wireguard/peers
|
||||
#var/ipfire/wireguard/settings
|
||||
var/ipfire/wireguard-functions.pl
|
||||
var/ipfire/wireless
|
||||
#var/ipfire/wireless/config
|
||||
#var/ipfire/wireless/settings
|
||||
var/ipfire/ddos
|
||||
var/ipfire/loxilb
|
||||
var/ipfire/xdpdns
|
||||
var/ipfire/xdpsni
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#etc/dnsdist.conf-dist
|
||||
etc/dnsdist.conf-dist
|
||||
etc/dnsdist-xsk.conf
|
||||
etc/rc.d/init.d/dnsdist
|
||||
usr/bin/dnsdist
|
||||
#usr/share/man/man1/dnsdist.1
|
||||
7
config/rootfiles/common/haproxy
Normal file
7
config/rootfiles/common/haproxy
Normal file
@@ -0,0 +1,7 @@
|
||||
etc/logrotate.d/haproxy
|
||||
etc/rc.d/init.d/haproxy
|
||||
etc/rc.d/rc3.d/S35haproxy
|
||||
usr/sbin/haproxy
|
||||
var/ipfire/backup/addons/includes/haproxy
|
||||
var/lib/haproxy
|
||||
var/ipfire/haproxy
|
||||
@@ -1,5 +1,4 @@
|
||||
#etc/keepalived
|
||||
etc/keepalived/keepalived.conf.sample
|
||||
etc/keepalived/samples
|
||||
#etc/keepalived/samples/keepalived.conf.HTTP_GET.port
|
||||
#etc/keepalived/samples/keepalived.conf.IPv6
|
||||
@@ -38,3 +37,5 @@ usr/sbin/keepalived
|
||||
#usr/share/man/man5/keepalived.conf.5
|
||||
#usr/share/man/man8/keepalived.8
|
||||
var/ipfire/backup/addons/includes/keepalived
|
||||
var/ipfire/keepalived
|
||||
etc/rc.d/rc3.d/S101keepalived
|
||||
6
config/rootfiles/common/kexec-tools
Normal file
6
config/rootfiles/common/kexec-tools
Normal file
@@ -0,0 +1,6 @@
|
||||
usr/lib/kexec-tools
|
||||
usr/lib/kexec-tools/kexec_test
|
||||
usr/sbin/kexec
|
||||
usr/sbin/vmcore-dmesg
|
||||
#usr/share/man/man8/kexec.8
|
||||
#usr/share/man/man8/vmcore-dmesg.8
|
||||
4
config/rootfiles/common/libbpf
Normal file
4
config/rootfiles/common/libbpf
Normal file
@@ -0,0 +1,4 @@
|
||||
usr/lib/libbpf.a
|
||||
usr/lib/libbpf.so
|
||||
usr/lib/libbpf.so.1
|
||||
usr/lib/libbpf.so.1.4.6
|
||||
5
config/rootfiles/common/libbpf-bootstrap
Normal file
5
config/rootfiles/common/libbpf-bootstrap
Normal file
@@ -0,0 +1,5 @@
|
||||
usr/bin/kprobe
|
||||
usr/bin/ksyscall
|
||||
usr/bin/profile
|
||||
usr/bin/netqtop
|
||||
usr/bin/wg_handshake
|
||||
9
config/rootfiles/common/libbsd
Normal file
9
config/rootfiles/common/libbsd
Normal file
@@ -0,0 +1,9 @@
|
||||
usr/lib/libbsd-ctor.a
|
||||
usr/lib/libbsd.a
|
||||
usr/lib/libbsd.la
|
||||
usr/lib/libbsd.so
|
||||
usr/lib/libbsd.so.0
|
||||
usr/lib/libbsd.so.0.12.2
|
||||
usr/lib/pkgconfig/libbsd-ctor.pc
|
||||
usr/lib/pkgconfig/libbsd-overlay.pc
|
||||
usr/lib/pkgconfig/libbsd.pc
|
||||
6
config/rootfiles/common/libmd
Normal file
6
config/rootfiles/common/libmd
Normal file
@@ -0,0 +1,6 @@
|
||||
usr/lib/libmd.a
|
||||
usr/lib/libmd.la
|
||||
usr/lib/libmd.so
|
||||
usr/lib/libmd.so.0
|
||||
usr/lib/libmd.so.0.1.0
|
||||
usr/lib/pkgconfig/libmd.pc
|
||||
1
config/rootfiles/common/loxicmd
Normal file
1
config/rootfiles/common/loxicmd
Normal file
@@ -0,0 +1 @@
|
||||
usr/bin/loxicmd
|
||||
7
config/rootfiles/common/loxilb
Normal file
7
config/rootfiles/common/loxilb
Normal file
@@ -0,0 +1,7 @@
|
||||
opt/loxilb/llb_ebpf_emain.o
|
||||
opt/loxilb/llb_ebpf_main.o
|
||||
opt/loxilb/llb_kern_sock.o
|
||||
opt/loxilb/llb_xdp_main.o
|
||||
opt/loxilb/loxilb_libdp.o
|
||||
usr/bin/loxilb
|
||||
etc/rc.d/rc3.d/S100loxilb
|
||||
1
config/rootfiles/common/makedumpfile
Normal file
1
config/rootfiles/common/makedumpfile
Normal file
@@ -0,0 +1 @@
|
||||
usr/sbin/makedumpfile
|
||||
@@ -35,6 +35,13 @@ usr/local/bin/updxlratorctrl
|
||||
usr/local/bin/urlfilterctrl
|
||||
#usr/local/bin/wiohelper
|
||||
#usr/local/bin/wioscan
|
||||
usr/local/bin/wireguardctrl
|
||||
usr/local/bin/wirelessclient
|
||||
usr/local/bin/wirelessctrl
|
||||
#usr/local/bin/wlanapctrl
|
||||
usr/local/bin/ddosctrl
|
||||
usr/local/bin/loxilbctrl
|
||||
usr/local/bin/keepalivedctrl
|
||||
usr/local/bin/xdpdnsctrl
|
||||
usr/local/bin/xdpsnictrl
|
||||
usr/local/bin/xdpgeoipctrl
|
||||
|
||||
@@ -23,6 +23,7 @@ usr/lib/openssh/sftp-server
|
||||
usr/lib/openssh/ssh-pkcs11-helper
|
||||
usr/lib/openssh/ssh-sk-helper
|
||||
usr/sbin/sshd
|
||||
usr/lib/openssh/sshd-session
|
||||
#usr/share/man/man1/scp.1
|
||||
#usr/share/man/man1/sftp.1
|
||||
#usr/share/man/man1/ssh-add.1
|
||||
|
||||
30
config/rootfiles/common/perl-Net-ISP-Balance
Normal file
30
config/rootfiles/common/perl-Net-ISP-Balance
Normal file
@@ -0,0 +1,30 @@
|
||||
etc/balance
|
||||
etc/balance.conf
|
||||
etc/balance/firewall
|
||||
etc/balance/firewall/01.accept
|
||||
etc/balance/firewall/01.accept.pl
|
||||
etc/balance/firewall/02.forward.pl
|
||||
etc/balance/lsm
|
||||
etc/balance/lsm/balancer_event_script
|
||||
etc/balance/lsm/default_script
|
||||
etc/balance/post-run
|
||||
etc/balance/post-run/post-run-script.pl
|
||||
etc/balance/pre-run
|
||||
etc/balance/pre-run/pre-run-script.pl
|
||||
etc/balance/routes
|
||||
etc/balance/routes/01.local_routes
|
||||
etc/balance/routes/02.local_routes.pl
|
||||
etc/load_balance.pl
|
||||
usr/bin/foolsm
|
||||
usr/bin/load_balance.pl
|
||||
usr/lib/perl5/site_perl/5.36.0/Net/ISP
|
||||
usr/lib/perl5/site_perl/5.36.0/Net/ISP/Balance
|
||||
usr/lib/perl5/site_perl/5.36.0/Net/ISP/Balance.pm
|
||||
usr/lib/perl5/site_perl/5.36.0/Net/ISP/Balance/ConfigData.pm
|
||||
#usr/lib/perl5/site_perl/5.36.0/x86_64-linux-thread-multi/auto/Net/ISP
|
||||
#usr/lib/perl5/site_perl/5.36.0/x86_64-linux-thread-multi/auto/Net/ISP/Balance
|
||||
#usr/lib/perl5/site_perl/5.36.0/x86_64-linux-thread-multi/auto/Net/ISP/Balance/.packlist
|
||||
#usr/share/man/man1/load_balance.pl.1
|
||||
#usr/share/man/man3/Net::ISP::Balance.3
|
||||
#usr/share/man/man3/Net::ISP::Balance::ConfigData.3
|
||||
var/lib/foolsm
|
||||
5
config/rootfiles/common/perl-Net-Netmask
Normal file
5
config/rootfiles/common/perl-Net-Netmask
Normal file
@@ -0,0 +1,5 @@
|
||||
usr/lib/perl5/site_perl/5.36.0/Net/Netmask.pm
|
||||
#usr/lib/perl5/site_perl/5.36.0/Net/Netmask.pod
|
||||
#usr/lib/perl5/site_perl/5.36.0/x86_64-linux-thread-multi/auto/Net/Netmask
|
||||
#usr/lib/perl5/site_perl/5.36.0/x86_64-linux-thread-multi/auto/Net/Netmask/.packlist
|
||||
#usr/share/man/man3/Net::Netmask.3
|
||||
1
config/rootfiles/common/pwru
Normal file
1
config/rootfiles/common/pwru
Normal file
@@ -0,0 +1 @@
|
||||
usr/bin/pwru
|
||||
@@ -1,8 +1,10 @@
|
||||
etc/suricata
|
||||
etc/suricata/suricata.yaml
|
||||
etc/suricata/suricata-xdp.yaml
|
||||
usr/bin/suricata
|
||||
#usr/include/suricata-plugin.h
|
||||
usr/sbin/convert-ids-backend-files
|
||||
usr/lib/bpf/xdp_filter.bpf
|
||||
#usr/share/doc/suricata
|
||||
#usr/share/doc/suricata/AUTHORS
|
||||
#usr/share/doc/suricata/Basic_Setup.txt
|
||||
|
||||
@@ -11,7 +11,7 @@ etc/unbound/unbound.conf
|
||||
#usr/lib/libunbound.la
|
||||
#usr/lib/libunbound.so
|
||||
usr/lib/libunbound.so.8
|
||||
usr/lib/libunbound.so.8.1.24
|
||||
usr/lib/libunbound.so.8.1.30
|
||||
#usr/lib/pkgconfig/libunbound.pc
|
||||
usr/sbin/unbound
|
||||
usr/sbin/unbound-anchor
|
||||
@@ -19,6 +19,7 @@ usr/sbin/unbound-checkconf
|
||||
usr/sbin/unbound-control
|
||||
usr/sbin/unbound-control-setup
|
||||
usr/sbin/unbound-dhcp-leases-bridge
|
||||
usr/sbin/unbound-dhcp-leases-client
|
||||
usr/sbin/unbound-host
|
||||
#usr/share/man/man1/unbound-host.1
|
||||
#usr/share/man/man3/libunbound.3
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
etc/vimrc
|
||||
root/.vimrc
|
||||
usr/bin/ex
|
||||
usr/bin/rview
|
||||
usr/bin/rvim
|
||||
|
||||
@@ -86,10 +86,18 @@ srv/web/ipfire/cgi-bin/wakeonlan.cgi
|
||||
srv/web/ipfire/cgi-bin/webaccess.cgi
|
||||
#srv/web/ipfire/cgi-bin/wio.cgi
|
||||
#srv/web/ipfire/cgi-bin/wiographs.cgi
|
||||
srv/web/ipfire/cgi-bin/wireguard.cgi
|
||||
srv/web/ipfire/cgi-bin/wireless.cgi
|
||||
srv/web/ipfire/cgi-bin/wirelessclient.cgi
|
||||
srv/web/ipfire/cgi-bin/wlanap.cgi
|
||||
srv/web/ipfire/cgi-bin/zoneconf.cgi
|
||||
srv/web/ipfire/cgi-bin/ddos.cgi
|
||||
srv/web/ipfire/cgi-bin/loxilb.cgi
|
||||
srv/web/ipfire/cgi-bin/loxilbconfig.cgi
|
||||
srv/web/ipfire/cgi-bin/loxilbfw.cgi
|
||||
srv/web/ipfire/cgi-bin/keepalived.cgi
|
||||
srv/web/ipfire/cgi-bin/xdpdns.cgi
|
||||
srv/web/ipfire/cgi-bin/xdpsni.cgi
|
||||
#srv/web/ipfire/html
|
||||
srv/web/ipfire/html/blob.gif
|
||||
#srv/web/ipfire/html/captive
|
||||
|
||||
4
config/rootfiles/common/wireguard-tools
Normal file
4
config/rootfiles/common/wireguard-tools
Normal file
@@ -0,0 +1,4 @@
|
||||
etc/fcron.cyclic/wg-dynamic
|
||||
usr/bin/wg
|
||||
#usr/share/bash-completion/completions/wg
|
||||
#usr/share/man/man8/wg.8
|
||||
@@ -10,6 +10,7 @@ etc/rc.d/helper/oci-setup
|
||||
#etc/rc.d/init.d
|
||||
etc/rc.d/init.d/acpid
|
||||
etc/rc.d/init.d/apache
|
||||
etc/rc.d/init.d/arpwatch
|
||||
etc/rc.d/init.d/beep
|
||||
etc/rc.d/init.d/checkfs
|
||||
etc/rc.d/init.d/cleanfs
|
||||
@@ -90,18 +91,30 @@ etc/rc.d/init.d/udev_retry
|
||||
etc/rc.d/init.d/unbound
|
||||
etc/rc.d/init.d/vnstat
|
||||
etc/rc.d/init.d/waitdrives
|
||||
etc/rc.d/init.d/wireguard
|
||||
etc/rc.d/init.d/wlanclient
|
||||
etc/rc.d/init.d/ddos
|
||||
etc/rc.d/init.d/loxilb
|
||||
etc/rc.d/init.d/xdpdns
|
||||
etc/rc.d/init.d/xdpsni
|
||||
etc/rc.d/init.d/xdpgeoip
|
||||
etc/rc.d/init.d/kdump-config
|
||||
etc/rc.d/init.d/kdump-init-functions
|
||||
etc/rc.d/init.d/kdump-tools
|
||||
etc/rc.d/init.d/kdump-vars.sh
|
||||
#etc/rc.d/rc0.d
|
||||
#etc/rc.d/rc0.d/K01imspetor
|
||||
#etc/rc.d/rc0.d/K01motion
|
||||
#etc/rc.d/rc0.d/K01vdradmin
|
||||
#etc/rc.d/rc0.d/K02sslh
|
||||
etc/rc.d/rc0.d/K08fcron
|
||||
etc/rc.d/rc0.d/K12arpwatch
|
||||
etc/rc.d/rc0.d/K28apache
|
||||
etc/rc.d/rc0.d/K30sshd
|
||||
etc/rc.d/rc0.d/K47setclock
|
||||
etc/rc.d/rc0.d/K49cyrus-sasl
|
||||
etc/rc.d/rc0.d/K51vnstat
|
||||
etc/rc.d/rc0.d/K70wireguard
|
||||
etc/rc.d/rc0.d/K77conntrackd
|
||||
etc/rc.d/rc0.d/K78suricata
|
||||
etc/rc.d/rc0.d/K79leds
|
||||
@@ -133,6 +146,8 @@ etc/rc.d/rc3.d/S24cyrus-sasl
|
||||
etc/rc.d/rc3.d/S30sshd
|
||||
etc/rc.d/rc3.d/S32apache
|
||||
etc/rc.d/rc3.d/S40fcron
|
||||
etc/rc.d/rc3.d/S50wireguard
|
||||
etc/rc.d/rc3.d/S64arpwatch
|
||||
etc/rc.d/rc3.d/S98rc.local
|
||||
#etc/rc.d/rc3.d/S98sslh
|
||||
#etc/rc.d/rc3.d/S99imspetor
|
||||
@@ -144,11 +159,13 @@ etc/rc.d/rc3.d/S98rc.local
|
||||
#etc/rc.d/rc6.d/K01vdradmin
|
||||
#etc/rc.d/rc6.d/K02sslh
|
||||
etc/rc.d/rc6.d/K08fcron
|
||||
etc/rc.d/rc6.d/K12arpwatch
|
||||
etc/rc.d/rc6.d/K28apache
|
||||
etc/rc.d/rc6.d/K30sshd
|
||||
etc/rc.d/rc6.d/K47setclock
|
||||
etc/rc.d/rc6.d/K49cyrus-sasl
|
||||
etc/rc.d/rc6.d/K51vnstat
|
||||
etc/rc.d/rc6.d/K70wireguard
|
||||
etc/rc.d/rc6.d/K77conntrackd
|
||||
etc/rc.d/rc6.d/K78suricata
|
||||
etc/rc.d/rc6.d/K79leds
|
||||
@@ -192,3 +209,4 @@ etc/sysconfig/modules
|
||||
etc/sysconfig/ramdisk
|
||||
etc/sysconfig/rc
|
||||
etc/sysconfig/rc.local
|
||||
etc/sysconfig/arpwatch
|
||||
|
||||
@@ -23699,3 +23699,5 @@ lib/modules/KVER-ipfire/modules.symbols
|
||||
lib/modules/KVER-ipfire/modules.symbols.bin
|
||||
#lib/modules/KVER-ipfire/source
|
||||
sbin/gen_init_cpio
|
||||
usr/sbin/bpftool
|
||||
usr/sbin/perf
|
||||
|
||||
52
config/rootfiles/common/xdp-tools
Normal file
52
config/rootfiles/common/xdp-tools
Normal file
@@ -0,0 +1,52 @@
|
||||
usr/lib/bpf/xdp-dispatcher.o
|
||||
usr/lib/bpf/xdp_synproxy.bpf.o
|
||||
etc/rc.d/rc3.d/S105ddos
|
||||
usr/lib/bpf/xdp_dnsrrl.bpf.o
|
||||
usr/lib/bpf/xdp_udp.bpf.o
|
||||
usr/lib/bpf/xdp_dns.bpf.o
|
||||
usr/lib/bpf/xdp_sni.bpf.o
|
||||
usr/lib/bpf/xdp_geoip.bpf.o
|
||||
usr/lib/bpf/xdp_udpddos.bpf.o
|
||||
usr/lib/bpf/dnsdist_xdp.bpf.o
|
||||
usr/lib/bpf/class_filter.bpf.o
|
||||
usr/sbin/xdp-udp
|
||||
usr/sbin/xdp_dns
|
||||
etc/rc.d/rc3.d/S102xdpdns
|
||||
usr/sbin/xdp_dns_log
|
||||
usr/sbin/xdp_sni
|
||||
usr/sbin/xdp_sni_log
|
||||
etc/rc.d/rc3.d/S103xdpsni
|
||||
usr/sbin/xdp_geoip
|
||||
etc/rc.d/rc3.d/S104xdpgeoip
|
||||
usr/lib/bpf/xdpdump_bpf.o
|
||||
usr/lib/bpf/xdpdump_xdp.o
|
||||
usr/lib/bpf/xdpfilt_alw_all.o
|
||||
usr/lib/bpf/xdpfilt_alw_eth.o
|
||||
usr/lib/bpf/xdpfilt_alw_ip.o
|
||||
usr/lib/bpf/xdpfilt_alw_tcp.o
|
||||
usr/lib/bpf/xdpfilt_alw_udp.o
|
||||
usr/lib/bpf/xdpfilt_dny_all.o
|
||||
usr/lib/bpf/xdpfilt_dny_eth.o
|
||||
usr/lib/bpf/xdpfilt_dny_ip.o
|
||||
usr/lib/bpf/xdpfilt_dny_tcp.o
|
||||
usr/lib/bpf/xdpfilt_dny_udp.o
|
||||
usr/lib/bpf/xsk_def_xdp_prog.o
|
||||
usr/lib/bpf/xsk_def_xdp_prog_5.3.o
|
||||
usr/lib/libxdp.a
|
||||
usr/lib/libxdp.so
|
||||
usr/lib/libxdp.so.1
|
||||
usr/lib/libxdp.so.1.5.0
|
||||
usr/lib/pkgconfig/libxdp.pc
|
||||
usr/sbin/xdp-bench
|
||||
usr/sbin/xdp-filter
|
||||
usr/sbin/xdp-loader
|
||||
usr/sbin/tc-loader
|
||||
usr/lib/bpf/tc-dummy.bpf.o
|
||||
usr/sbin/xdp-monitor
|
||||
usr/sbin/xdp-trafficgen
|
||||
usr/sbin/xdp_synproxy
|
||||
usr/sbin/xdp-udp
|
||||
usr/sbin/xdpdump
|
||||
usr/sbin/class_filter
|
||||
usr/share/xdp-tools/xdp_drop.o
|
||||
usr/share/xdp-tools/xdp_pass.o
|
||||
1055
config/suricata/suricata-xdp.yaml
Normal file
1055
config/suricata/suricata-xdp.yaml
Normal file
File diff suppressed because it is too large
Load Diff
75
config/unbound/unbound-dhcp-leases-client
Normal file
75
config/unbound/unbound-dhcp-leases-client
Normal file
@@ -0,0 +1,75 @@
|
||||
#!/bin/bash
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2016 Michael Tremer #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
SOCKET="/var/run/unbound-dhcp-leases-bridge.sock"
|
||||
|
||||
main() {
|
||||
local event="${1}"
|
||||
shift
|
||||
|
||||
# Check if we have received an event
|
||||
if [ -z "${event}" ]; then
|
||||
echo "${0}: Missing event" >&2
|
||||
return 2
|
||||
fi
|
||||
|
||||
# Check if the socket exists
|
||||
if [ ! -S "${SOCKET}" ]; then
|
||||
echo "${0}: ${SOCKET} does not exist" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Connect to the socket
|
||||
coproc NC { nc -U "${SOCKET}"; }
|
||||
|
||||
local arg
|
||||
local response
|
||||
|
||||
# Send the message
|
||||
{
|
||||
# Send the event
|
||||
echo "EVENT=${event}"
|
||||
|
||||
# Send all arguments
|
||||
for arg in $@; do
|
||||
echo "${arg}"
|
||||
done
|
||||
} >&"${NC[1]}"
|
||||
|
||||
# Close the input part of the connection
|
||||
exec {NC[1]}>&-
|
||||
|
||||
# Capture the response
|
||||
read response <&"${NC[0]}"
|
||||
|
||||
case "${response}" in
|
||||
OK)
|
||||
return 0
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "${response}" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
main "$@" || exit $?
|
||||
1
config/vim/.vimrc
Normal file
1
config/vim/.vimrc
Normal file
@@ -0,0 +1 @@
|
||||
set mouse-=a
|
||||
122
config/wireguard/wg-dynamic
Normal file
122
config/wireguard/wg-dynamic
Normal file
@@ -0,0 +1,122 @@
|
||||
#!/bin/bash
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2024 Michael Tremer <michael.tremer@ipfire.org> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
# #
|
||||
# This script tries to keep WireGuard connections with dynamic peers alive #
|
||||
# #
|
||||
# It resolves the endpoint if it is an FQDN, and if so, will check if the #
|
||||
# currently connected endpoint matches any of the resolved IP addresses. If #
|
||||
# not it will reload the WireGuard configuration in the hope that wg will #
|
||||
# update the kernel with the new IP address and the connection comes back up #
|
||||
# again. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
. /etc/sysconfig/rc
|
||||
. ${rc_functions}
|
||||
|
||||
# Fetches the first endpoint that is currently active on the given interface
|
||||
current_endpoint() {
|
||||
local intf="${1}"
|
||||
|
||||
local pubkey
|
||||
local endpoint
|
||||
|
||||
# List the first endpoint (are there even more than one?)
|
||||
wg show "${intf}" endpoints | while read -r pubkey endpoint; do
|
||||
echo "${endpoint%:*}"
|
||||
break
|
||||
done
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Resolves a hostname
|
||||
resolve() {
|
||||
local endpoint="${1}"
|
||||
|
||||
dig +short "A" "${endpoint}" 2>/dev/null
|
||||
}
|
||||
|
||||
main() {
|
||||
local -A settings=()
|
||||
|
||||
# Read WireGuard settings
|
||||
readhash settings /var/ipfire/wireguard/settings
|
||||
|
||||
# Do nothing if WireGuard is not enabled
|
||||
if [ "${settings[ENABLED]}" != "on" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
local line
|
||||
while IFS=',' read -r -a line; do
|
||||
local id="${line[0]}"
|
||||
local enabled="${line[1]}"
|
||||
local type="${line[2]}"
|
||||
local name="${line[3]}"
|
||||
local endpoint="${line[7]}"
|
||||
|
||||
# Only process enabled net-to-net connections
|
||||
case "${enabled},${type}" in
|
||||
on,net)
|
||||
;;
|
||||
*)
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
|
||||
# The endpoint must be an FQDN
|
||||
case "${endpoint}" in
|
||||
# Ignore IP addresses
|
||||
[0-9]*.[0-9]*.[0-9]*.[0-9]*)
|
||||
continue
|
||||
;;
|
||||
|
||||
# Ignore if we don't know the endpoint
|
||||
"")
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
|
||||
local address
|
||||
local match=0
|
||||
|
||||
# Fetch the current endpoint address
|
||||
local current_address="$(current_endpoint "wg${id}")"
|
||||
|
||||
# Walk through all IP addresses the FQDN resolves to
|
||||
for address in $(resolve "${endpoint}"); do
|
||||
if [ "${current_address}" = "${address}" ]; then
|
||||
match=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# If there has been no match, we have to reload everything
|
||||
if [ "${match}" -eq 0 ]; then
|
||||
exec /etc/init.d/wireguard reload
|
||||
fi
|
||||
done < /var/ipfire/wireguard/peers
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
main "$@" || exit $?
|
||||
@@ -1559,6 +1559,7 @@ WARNING: untranslated string: proxy reports today = Today
|
||||
WARNING: untranslated string: proxy reports weekly = Weekly reports
|
||||
WARNING: untranslated string: ptr = PTR
|
||||
WARNING: untranslated string: ptr lookup failed = Reverse lookup failed
|
||||
WARNING: untranslated string: public key = unknown string
|
||||
WARNING: untranslated string: pulse = Pulse
|
||||
WARNING: untranslated string: pulse dial = Pulse dial:
|
||||
WARNING: untranslated string: qos enter bandwidths = You will need to enter your downstream and upstream bandwidth!
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007 Michael Tremer & Christian Schmidt #
|
||||
# Copyright (C) 2007-2025 IPFire Team <info@ipfire.org> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
@@ -20,10 +20,8 @@
|
||||
###############################################################################
|
||||
|
||||
use CGI qw(param);
|
||||
use Apache::Htpasswd;
|
||||
use Crypt::PasswdMD5;
|
||||
|
||||
$swroot = "/var/ipfire";
|
||||
require '/var/ipfire/general-functions.pl';
|
||||
|
||||
my %cgiparams;
|
||||
my %mainsettings;
|
||||
@@ -32,8 +30,8 @@ my %proxysettings;
|
||||
$proxysettings{'NCSA_MIN_PASS_LEN'} = 6;
|
||||
|
||||
### Initialize environment
|
||||
&readhash("${swroot}/main/settings", \%mainsettings);
|
||||
&readhash("${swroot}/proxy/advanced/settings", \%proxysettings);
|
||||
&readhash("${General::swroot}/main/settings", \%mainsettings);
|
||||
&readhash("${General::swroot}/proxy/advanced/settings", \%proxysettings);
|
||||
$language = $mainsettings{'LANGUAGE'};
|
||||
|
||||
### Initialize language
|
||||
@@ -42,12 +40,12 @@ if ($language =~ /^(\w+)$/) {$language = $1;}
|
||||
# Uncomment this to force a certain language:
|
||||
# $language='en';
|
||||
#
|
||||
require "${swroot}/langs/en.pl";
|
||||
require "${swroot}/langs/${language}.pl";
|
||||
require "${General::swroot}/langs/en.pl";
|
||||
require "${General::swroot}/langs/${language}.pl";
|
||||
|
||||
my $userdb = "$swroot/proxy/advanced/ncsa/passwd";
|
||||
my $userdb = "$General::swroot/proxy/advanced/ncsa/passwd";
|
||||
|
||||
&readhash("$swroot/ethernet/settings", \%netsettings);
|
||||
&readhash("$General::swroot/ethernet/settings", \%netsettings);
|
||||
|
||||
my $success = 0;
|
||||
|
||||
@@ -76,20 +74,13 @@ if ($cgiparams{'SUBMIT'} eq $tr{'advproxy chgwebpwd change password'})
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
my $htpasswd = new Apache::Htpasswd("$userdb");
|
||||
|
||||
# Check if a user with this name exists
|
||||
my $old_password = $htpasswd->fetchPass($cgiparams{'USERNAME'});
|
||||
if (!$old_password) {
|
||||
$errormessage = $tr{'advproxy errmsg invalid user'};
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
# Reset password
|
||||
if (!$htpasswd->htpasswd($cgiparams{'USERNAME'}, $cgiparams{'NEW_PASSWORD_1'},
|
||||
$cgiparams{'OLD_PASSWORD'})) {
|
||||
$errormessage = $tr{'advproxy errmsg password incorrect'};
|
||||
# If the htpasswd verification status is 0 then update the database
|
||||
# otherwise respond with an error message.
|
||||
if (&General::system("/usr/bin/htpasswd", "-bv", "$userdb", "$cgiparams{'USERNAME'}", "$cgiparams{'OLD_PASSWORD'}") != 0) {
|
||||
$errormessage = $tr{'advproxy errmsg invalid user/password'};
|
||||
goto ERROR;
|
||||
} else {
|
||||
&General::system("/usr/bin/htpasswd", "-bB", "-C 10", "$userdb", "$cgiparams{'USERNAME'}", "$cgiparams{'NEW_PASSWORD_1'}");
|
||||
}
|
||||
|
||||
$success = 1;
|
||||
|
||||
@@ -38,11 +38,17 @@ require "${General::swroot}/header.pl";
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'donation'});
|
||||
|
||||
print <<END
|
||||
<p>$Lang::tr{'donation-text'}</p>
|
||||
|
||||
<p>$Lang::tr{'donation-bpfire-text'}</p>
|
||||
<div align="center">
|
||||
<a href="https://www.ipfire.org/donate">
|
||||
<strong>$Lang::tr{'donation'}</strong>
|
||||
<a href="https://www.paypal.com/donate/?business=BL97G8687E5B6&no_recurring=0&item_name=Make+revolutionary+eBPF+technology+available+for+non-tech+savvy+users+for+safe+online+surfing¤cy_code=USD" target="_blank">
|
||||
<strong>$Lang::tr{'donation-bpfire'}</strong>
|
||||
</a>
|
||||
</div>
|
||||
<p>$Lang::tr{'donation-ipfire-text'}</p>
|
||||
<div align="center">
|
||||
|
||||
<a href="https://www.ipfire.org/donate" target="_blank">
|
||||
<strong>$Lang::tr{'donation-ipfire'}</strong>
|
||||
</a>
|
||||
</div>
|
||||
END
|
||||
@@ -54,7 +60,7 @@ END
|
||||
print <<END
|
||||
<br>
|
||||
<center>
|
||||
$Lang::tr{'visit us at'}: <b><a href='https://www.ipfire.org/' target="_blank">https://www.ipfire.org/</a></b>
|
||||
$Lang::tr{'visit us at'}: <b><a href='http://www.bpfire.net/' target="_blank">https://www.bpfire.net/</a></b> <b><a href='https://www.ipfire.org/' target="_blank">https://www.ipfire.org/</a></b>
|
||||
</center>
|
||||
<br><br>
|
||||
|
||||
|
||||
@@ -523,17 +523,19 @@ print <<END
|
||||
<td><input type='checkbox' name='ENABLED' $checked{'ENABLED'}{'on'} /></td>
|
||||
|
||||
<td class='username'>$Lang::tr{'username'}</td>
|
||||
<td class='username'><input type='text' name='LOGIN' value='$settings{'LOGIN'}' /></td>
|
||||
<td class='username'><input type='text' name='LOGIN'
|
||||
value='@{[ &Header::escape($settings{'LOGIN'}) ]}' /></td>
|
||||
|
||||
<td class='token' style='display:none'>$Lang::tr{'token'}</td>
|
||||
<td class='token' style='display:none'><input type='text' name='TOKEN' value='$settings{'TOKEN'}' /></td>
|
||||
<td class='token' style='display:none'><input type='text' name='TOKEN'
|
||||
value='@{[ &Header::escape($settings{'TOKEN'}) ]}' /></td>
|
||||
</tr>
|
||||
|
||||
<tr class='password'>
|
||||
<td class='base'></td>
|
||||
<td></td>
|
||||
<td class='base'>$Lang::tr{'password'}</td>
|
||||
<td><input type='password' name='PASSWORD' value='$settings{'PASSWORD'}' /></td>
|
||||
<td><input type='password' name='PASSWORD' value='@{[ &Header::escape($settings{'PASSWORD'}) ]}' /></td>
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
|
||||
546
html/cgi-bin/ddos.cgi
Executable file
546
html/cgi-bin/ddos.cgi
Executable file
@@ -0,0 +1,546 @@
|
||||
#!/usr/bin/perl
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2020 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2024 BPFire <vincent.mc.li@gmail.com> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
use strict;
|
||||
|
||||
# enable only the following on debugging purpose
|
||||
#use warnings;
|
||||
#use CGI::Carp 'fatalsToBrowser';
|
||||
|
||||
use IO::Socket;
|
||||
|
||||
require '/var/ipfire/general-functions.pl';
|
||||
require "${General::swroot}/location-functions.pl";
|
||||
require "${General::swroot}/lang.pl";
|
||||
require "${General::swroot}/header.pl";
|
||||
|
||||
my %color = ();
|
||||
my %mainsettings = ();
|
||||
my %ddossettings=();
|
||||
my %udpddossettings=();
|
||||
my %dnsddossettings=();
|
||||
my %checked=();
|
||||
my $errormessage='';
|
||||
my $counter = 0;
|
||||
my %tcp_ports=();
|
||||
my %udp_ports=();
|
||||
my $tcp_portfile = "${General::swroot}/ddos/tcp_ports";
|
||||
my $udp_portfile = "${General::swroot}/ddos/udp_ports";
|
||||
my $ddossettingfile = "${General::swroot}/ddos/settings";
|
||||
my $udpddossettingfile = "${General::swroot}/ddos/udp-ddos-settings";
|
||||
my $dnsddossettingfile = "${General::swroot}/ddos/dns-ddos-settings";
|
||||
|
||||
&get_tcp_ports();
|
||||
&get_udp_ports();
|
||||
|
||||
# Read configuration file.
|
||||
|
||||
&General::readhash("${General::swroot}/main/settings", \%mainsettings);
|
||||
&General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", \%color);
|
||||
|
||||
&Header::showhttpheaders();
|
||||
|
||||
$ddossettings{'ENABLE_DDOS'} = 'off';
|
||||
$udpddossettings{'ENABLE_UDP_DDOS'} = 'off';
|
||||
$dnsddossettings{'ENABLE_DNS_DDOS'} = 'off';
|
||||
$ddossettings{'ACTION'} = '';
|
||||
$udpddossettings{'UDP_ACTION'} = '';
|
||||
$udpddossettings{'DNS_ACTION'} = '';
|
||||
|
||||
&Header::getcgihash(\%ddossettings);
|
||||
|
||||
if ($ddossettings{'ACTION'} eq $Lang::tr{'save'})
|
||||
{
|
||||
|
||||
# Loop through our locations array to prevent from
|
||||
# non existing countries or code.
|
||||
foreach my $p (values %tcp_ports) {
|
||||
# Check if blocking for this country should be enabled/disabled.
|
||||
if (exists $ddossettings{$p}) {
|
||||
$ddossettings{$p} = "on";
|
||||
} else {
|
||||
$ddossettings{$p} = "off";
|
||||
}
|
||||
}
|
||||
|
||||
&General::writehash("$ddossettingfile", \%ddossettings);
|
||||
|
||||
if ($ddossettings{'ENABLE_DDOS'} eq 'on') {
|
||||
&General::log($Lang::tr{'ddos is enabled'});
|
||||
&General::system('/usr/bin/touch', "${General::swroot}/ddos/enableddos");
|
||||
&General::system('/usr/local/bin/ddosctrl', 'start');
|
||||
} else {
|
||||
&General::log($Lang::tr{'ddos is disabled'});
|
||||
&General::system('/usr/local/bin/ddosctrl', 'stop');
|
||||
unlink "${General::swroot}/ddos/enableddos";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&Header::getcgihash(\%udpddossettings);
|
||||
|
||||
if ($udpddossettings{'UDP_ACTION'} eq $Lang::tr{'save'})
|
||||
{
|
||||
|
||||
# Loop through our locations array to prevent from
|
||||
# non existing countries or code.
|
||||
foreach my $p (values %udp_ports) {
|
||||
# Check if blocking for this country should be enabled/disabled.
|
||||
if (exists $udpddossettings{$p}) {
|
||||
$udpddossettings{$p} = "on";
|
||||
} else {
|
||||
$udpddossettings{$p} = "off";
|
||||
}
|
||||
}
|
||||
|
||||
&General::writehash("$udpddossettingfile", \%udpddossettings);
|
||||
|
||||
if ($udpddossettings{'ENABLE_UDP_DDOS'} eq 'on') {
|
||||
&General::log($Lang::tr{'ddos is enabled'});
|
||||
&General::system('/usr/bin/touch', "${General::swroot}/ddos/enableddos");
|
||||
&General::system('/usr/local/bin/ddosctrl', 'start');
|
||||
} else {
|
||||
&General::log($Lang::tr{'ddos is disabled'});
|
||||
&General::system('/usr/local/bin/ddosctrl', 'stop');
|
||||
unlink "${General::swroot}/ddos/enableddos";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&Header::getcgihash(\%dnsddossettings);
|
||||
|
||||
if ($udpddossettings{'DNS_ACTION'} eq $Lang::tr{'save'})
|
||||
{
|
||||
|
||||
&General::writehash("$dnsddossettingfile", \%dnsddossettings);
|
||||
|
||||
if ($dnsddossettings{'ENABLE_DNS_DDOS'} eq 'on') {
|
||||
&General::log($Lang::tr{'ddos is enabled'});
|
||||
&General::system('/usr/bin/touch', "${General::swroot}/ddos/enableddos");
|
||||
&General::system('/usr/local/bin/ddosctrl', 'start');
|
||||
} else {
|
||||
&General::log($Lang::tr{'ddos is disabled'});
|
||||
&General::system('/usr/local/bin/ddosctrl', 'stop');
|
||||
unlink "${General::swroot}/ddos/enableddos";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&Header::openpage($Lang::tr{'ebpf xdp ddos'}, 1, '');
|
||||
|
||||
&Header::openbigbox('100%', 'left', '', $errormessage);
|
||||
|
||||
if ($errormessage) {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'error messages'});
|
||||
print "<font class='base' color=red>$errormessage </font>\n";
|
||||
&Header::closebox();
|
||||
}
|
||||
|
||||
# Read configuration file.
|
||||
&General::readhash("$ddossettingfile", \%ddossettings);
|
||||
|
||||
# Checkbox pre-selection.
|
||||
my $checked;
|
||||
if ($ddossettings{'ENABLE_DDOS'} eq "on") {
|
||||
$checked = "checked='checked'";
|
||||
}
|
||||
|
||||
# Print box to enable/disable locationblock.
|
||||
print"<form method='POST' action='$ENV{'SCRIPT_NAME'}'>\n";
|
||||
|
||||
&Header::openbox('100%', 'center', $Lang::tr{'xdp tcp'});
|
||||
print <<END;
|
||||
<table width='95%'>
|
||||
<tr>
|
||||
<td width='50%' class='base'>$Lang::tr{'xdp enable'}
|
||||
<td><input type='checkbox' name='ENABLE_DDOS' $checked></td>
|
||||
<td align='center'><input type='submit' name='ACTION' value='$Lang::tr{'save'}'></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
END
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::openbox('100%', 'center', $Lang::tr{'xdp tcp port'});
|
||||
print <<END;
|
||||
|
||||
<table width='95%' class='tbl' id="countries">
|
||||
<tr>
|
||||
<td width='5%' align='center' bgcolor='$color{'color20'}'></td>
|
||||
<td width='5%' align='center' bgcolor='$color{'color20'}'>
|
||||
<b>$Lang::tr{'port'}</b>
|
||||
</td>
|
||||
<td with='35%' align='left' bgcolor='$color{'color20'}'>
|
||||
<b>$Lang::tr{'service'}</b>
|
||||
</td>
|
||||
|
||||
<td width='5%' bgcolor='$color{'color20'}'> </td>
|
||||
|
||||
<td width='5%' align='center' bgcolor='$color{'color20'}'></td>
|
||||
<td width='5%' align='center' bgcolor='$color{'color20'}'>
|
||||
<b>$Lang::tr{'port'}</b>
|
||||
</td>
|
||||
<td with='35%' align='left' bgcolor='$color{'color20'}'>
|
||||
<b>$Lang::tr{'service'}</b>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
END
|
||||
|
||||
my $lines;
|
||||
my $lines2;
|
||||
my $col;
|
||||
|
||||
|
||||
# Sort output based on hash value port number
|
||||
for my $service ( sort { $tcp_ports{$a} cmp $tcp_ports{$b} }
|
||||
keys %tcp_ports )
|
||||
{
|
||||
my $port = $tcp_ports{$service};
|
||||
|
||||
# Checkbox pre-selection.
|
||||
my $checked;
|
||||
if ($ddossettings{$port} eq "on") {
|
||||
$checked = "checked='checked'";
|
||||
}
|
||||
|
||||
# Colour lines.
|
||||
if ($lines % 2) {
|
||||
$col="bgcolor='$color{'color20'}'";
|
||||
} else {
|
||||
$col="bgcolor='$color{'color22'}'";
|
||||
}
|
||||
|
||||
# Grouping elements.
|
||||
my $line_start;
|
||||
my $line_end;
|
||||
if ($lines2 % 2) {
|
||||
# Increase lines (background color by once.
|
||||
$lines++;
|
||||
|
||||
# Add empty column in front.
|
||||
$line_start="<td $col> </td>";
|
||||
|
||||
# When the line number can be diveded by "2",
|
||||
# we are going to close the line.
|
||||
$line_end="</tr>";
|
||||
} else {
|
||||
# When the line number is not divideable by "2",
|
||||
# we are starting a new line.
|
||||
$line_start="<tr>";
|
||||
$line_end;
|
||||
}
|
||||
|
||||
print "$line_start<td align='center' $col><input type='checkbox' name='$port' $checked></td>\n";
|
||||
print "<td align='center' $col>$port</td>\n";
|
||||
print "<td align='left' $col>$service</td>$line_end\n";
|
||||
|
||||
$lines2++;
|
||||
}
|
||||
|
||||
print <<END;
|
||||
</table>
|
||||
|
||||
END
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
print "</form>\n";
|
||||
#
|
||||
# Read configuration file.
|
||||
&General::readhash("$dnsddossettingfile", \%dnsddossettings);
|
||||
|
||||
# Checkbox pre-selection.
|
||||
my $dns_checked;
|
||||
if ($dnsddossettings{'ENABLE_DNS_DDOS'} eq "on") {
|
||||
$dns_checked = "checked='checked'";
|
||||
}
|
||||
|
||||
# Print box to enable/disable locationblock.
|
||||
print"<form method='POST' action='$ENV{'SCRIPT_NAME'}'>\n";
|
||||
|
||||
&Header::openbox('100%', 'center', $Lang::tr{'xdp dns'});
|
||||
print <<END;
|
||||
<table width='95%'>
|
||||
<tr>
|
||||
<td width='50%' class='base'>$Lang::tr{'xdp enable'}
|
||||
<td><input type='checkbox' name='ENABLE_DNS_DDOS' $dns_checked></td>
|
||||
<td align='center'><input type='submit' name='DNS_ACTION' value='$Lang::tr{'save'}'></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width='50%' class='base'>$Lang::tr{'xdp dns ratelimit'}
|
||||
<td><input type='text' name='DNS_RATELIMIT' value='$dnsddossettings{'DNS_RATELIMIT'}'</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
END
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
print "</form>\n";
|
||||
|
||||
# Read configuration file.
|
||||
&General::readhash("$udpddossettingfile", \%udpddossettings);
|
||||
|
||||
# Checkbox pre-selection.
|
||||
my $udp_checked;
|
||||
if ($udpddossettings{'ENABLE_UDP_DDOS'} eq "on") {
|
||||
$udp_checked = "checked='checked'";
|
||||
}
|
||||
|
||||
# Print box to enable/disable locationblock.
|
||||
print"<form method='POST' action='$ENV{'SCRIPT_NAME'}'>\n";
|
||||
|
||||
&Header::openbox('100%', 'center', $Lang::tr{'xdp udp'});
|
||||
print <<END;
|
||||
<table width='95%'>
|
||||
<tr>
|
||||
<td width='50%' class='base'>$Lang::tr{'xdp enable'}
|
||||
<td><input type='checkbox' name='ENABLE_UDP_DDOS' $udp_checked></td>
|
||||
<td align='center'><input type='submit' name='UDP_ACTION' value='$Lang::tr{'save'}'></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width='50%' class='base'>$Lang::tr{'xdp udp ratelimit'}
|
||||
<td><input type='text' name='UDP_RATELIMIT' value='$udpddossettings{'UDP_RATELIMIT'}'</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
END
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::openbox('100%', 'center', $Lang::tr{'xdp udp port'});
|
||||
print <<END;
|
||||
|
||||
<table width='95%' class='tbl' id="countries">
|
||||
<tr>
|
||||
<td width='5%' align='center' bgcolor='$color{'color20'}'></td>
|
||||
<td width='5%' align='center' bgcolor='$color{'color20'}'>
|
||||
<b>$Lang::tr{'port'}</b>
|
||||
</td>
|
||||
<td with='35%' align='left' bgcolor='$color{'color20'}'>
|
||||
<b>$Lang::tr{'service'}</b>
|
||||
</td>
|
||||
|
||||
<td width='5%' bgcolor='$color{'color20'}'> </td>
|
||||
|
||||
<td width='5%' align='center' bgcolor='$color{'color20'}'></td>
|
||||
<td width='5%' align='center' bgcolor='$color{'color20'}'>
|
||||
<b>$Lang::tr{'port'}</b>
|
||||
</td>
|
||||
<td with='35%' align='left' bgcolor='$color{'color20'}'>
|
||||
<b>$Lang::tr{'service'}</b>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
END
|
||||
|
||||
my $udp_lines;
|
||||
my $udp_lines2;
|
||||
my $udp_col;
|
||||
|
||||
# Sort output based on hash value port number
|
||||
for my $service ( sort { $udp_ports{$a} cmp $udp_ports{$b} }
|
||||
keys %udp_ports )
|
||||
{
|
||||
my $port = $udp_ports{$service};
|
||||
|
||||
# Checkbox pre-selection.
|
||||
my $checked;
|
||||
if ($udpddossettings{$port} eq "on") {
|
||||
$checked = "checked='checked'";
|
||||
}
|
||||
|
||||
# Colour lines.
|
||||
if ($udp_lines % 2) {
|
||||
$col="bgcolor='$color{'color20'}'";
|
||||
} else {
|
||||
$col="bgcolor='$color{'color22'}'";
|
||||
}
|
||||
|
||||
# Grouping elements.
|
||||
my $line_start;
|
||||
my $line_end;
|
||||
if ($udp_lines2 % 2) {
|
||||
# Increase lines (background color by once.
|
||||
$lines++;
|
||||
|
||||
# Add empty column in front.
|
||||
$line_start="<td $udp_col> </td>";
|
||||
|
||||
# When the line number can be diveded by "2",
|
||||
# we are going to close the line.
|
||||
$line_end="</tr>";
|
||||
} else {
|
||||
# When the line number is not divideable by "2",
|
||||
# we are starting a new line.
|
||||
$line_start="<tr>";
|
||||
$line_end;
|
||||
}
|
||||
|
||||
print "$line_start<td align='center' $udp_col><input type='checkbox' name='$port' $checked></td>\n";
|
||||
print "<td align='center' $udp_col>$port</td>\n";
|
||||
print "<td align='left' $udp_col>$service</td>$line_end\n";
|
||||
|
||||
$udp_lines2++;
|
||||
}
|
||||
print <<END;
|
||||
</table>
|
||||
|
||||
END
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
print "</form>\n";
|
||||
|
||||
&Header::openbox('100%', 'center', $Lang::tr{'xdp status'});
|
||||
|
||||
print <<END;
|
||||
<table class="tbl" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="center">
|
||||
<strong>$Lang::tr{'xdp interface'}</strong>
|
||||
</th>
|
||||
<th align="center">
|
||||
<strong>$Lang::tr{'xdp prio'}</strong>
|
||||
</th>
|
||||
<th align="center">
|
||||
<strong>$Lang::tr{'xdp program'}</strong>
|
||||
</th>
|
||||
<th align="center">
|
||||
<strong>$Lang::tr{'xdp mode'}</strong>
|
||||
</th>
|
||||
<th align="center">
|
||||
<strong>$Lang::tr{'xdp id'}</strong>
|
||||
</th>
|
||||
<th align="center">
|
||||
<strong>$Lang::tr{'xdp tag'}</strong>
|
||||
</th>
|
||||
<th align="center">
|
||||
<strong>$Lang::tr{'xdp action'}</strong>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
END
|
||||
|
||||
&printxdp();
|
||||
|
||||
print "</tbody>\n</table>\n";
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::closebigbox();
|
||||
|
||||
&Header::closepage();
|
||||
|
||||
sub get_tcp_ports()
|
||||
{
|
||||
my $fh;
|
||||
open($fh, '<', $tcp_portfile) or die "Unable to open file: $!";
|
||||
while (my $line = <$fh>) {
|
||||
chomp $line;
|
||||
next if $line =~ /^\s*#/; # Skip comments
|
||||
my ($service, $port) = $line =~ /^(\w+)\s+(\d+)\/tcp/;
|
||||
if ($service && $port) {
|
||||
$tcp_ports{$service} = $port;
|
||||
}
|
||||
}
|
||||
close($fh);
|
||||
}
|
||||
|
||||
sub get_udp_ports()
|
||||
{
|
||||
my $fh;
|
||||
open($fh, '<', $udp_portfile) or die "Unable to open file: $!";
|
||||
while (my $line = <$fh>) {
|
||||
chomp $line;
|
||||
next if $line =~ /^\s*#/; # Skip comments
|
||||
my ($service, $port) = $line =~ /^(\w+)\s+(\d+)\/udp/;
|
||||
if ($service && $port) {
|
||||
$udp_ports{$service} = $port;
|
||||
}
|
||||
}
|
||||
close($fh);
|
||||
}
|
||||
|
||||
sub printxdp()
|
||||
{
|
||||
# print active SSH logins (grep outpout of "who -s")
|
||||
my @output = &General::system_output("/usr/local/bin/ddosctrl", "status");
|
||||
chomp(@output);
|
||||
|
||||
# list active logins...
|
||||
foreach my $line (@output)
|
||||
{
|
||||
my $interface;
|
||||
my $prio;
|
||||
my $prog;
|
||||
my $mode;
|
||||
my $id;
|
||||
my $tag;
|
||||
my $action;
|
||||
#comment next below when having issue
|
||||
#next if $line !~ /^red0/;
|
||||
#next if $line !~ /^\s=>/;
|
||||
next if $line =~ /No XDP program loaded!/;
|
||||
if ($line =~ /^red0/) {
|
||||
my @arry = split(/\s+/, $line);
|
||||
$interface = $arry[0];
|
||||
$prio = "N/A";
|
||||
$prog = $arry[1];
|
||||
$mode = $arry[2];
|
||||
$id = $arry[3];
|
||||
$tag = $arry[4];
|
||||
$action = "N/A";
|
||||
} elsif ($line =~ /^\s=>/) {
|
||||
my @arry = split(/\s+/, $line);
|
||||
$interface = "red0";
|
||||
$prio = $arry[2];
|
||||
$prog = $arry[3];
|
||||
$mode = "N/A";
|
||||
$id = $arry[4];
|
||||
$tag = $arry[5];
|
||||
$action = $arry[6];
|
||||
}
|
||||
if ($line =~ /^red0/ or $line =~ /^\s=>/) {
|
||||
my $table_colour = ($id % 2) ? $color{'color20'} : $color{'color22'};
|
||||
|
||||
print <<END;
|
||||
<tr bgcolor='$table_colour'>
|
||||
<td>$interface</td>
|
||||
<td>$prio</td>
|
||||
<td>$prog</td>
|
||||
<td>$mode</td>
|
||||
<td>$id</td>
|
||||
<td>$tag</td>
|
||||
<td>$action</td>
|
||||
</tr>
|
||||
END
|
||||
;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -42,11 +42,19 @@ our $filename1 = "${General::swroot}/dhcp/advoptions"; # Field separator is TAB
|
||||
# because we need commas in the some data
|
||||
our $filename2 = "${General::swroot}/dhcp/fixleases";
|
||||
our $filename3 = "${General::swroot}/dhcp/advoptions-list"; # Describe the allowed syntax for dhcp options
|
||||
my $loxilbipfile = "${General::swroot}/loxilb/ipconfigfile";
|
||||
my $errormessage = '';
|
||||
my $warnNTPmessage = '';
|
||||
my @nosaved=();
|
||||
my %color = ();
|
||||
|
||||
our @IPFILE = ();
|
||||
|
||||
if (open(FILE, "$loxilbipfile")) {
|
||||
@IPFILE = <FILE>;
|
||||
close (FILE);
|
||||
}
|
||||
|
||||
#Basic syntax allowed for new Option definition. Not implemented: RECORDS & array of RECORDS
|
||||
our $OptionTypes = 'boolean|((un)?signed )?integer (8|16|32)|ip-address|text|string|encapsulate \w+|array of ip-address';
|
||||
|
||||
@@ -58,6 +66,7 @@ if (&Header::blue_used()){push(@ITFs,'BLUE');}
|
||||
foreach my $itf (@ITFs) {
|
||||
$dhcpsettings{"ENABLE_${itf}"} = 'off';
|
||||
$dhcpsettings{"ENABLEBOOTP_${itf}"} = 'off';
|
||||
$dhcpsettings{"ROUTER_ADDR_${itf}"} = '';
|
||||
$dhcpsettings{"START_ADDR_${itf}"} = '';
|
||||
$dhcpsettings{"END_ADDR_${itf}"} = '';
|
||||
$dhcpsettings{"DOMAIN_NAME_${itf}"} = '';
|
||||
@@ -144,6 +153,12 @@ if ($dhcpsettings{'ACTION'} eq $Lang::tr{'save'}) {
|
||||
foreach my $itf (@ITFs) {
|
||||
if ($dhcpsettings{"ENABLE_${itf}"} eq 'on' ) {
|
||||
# "Start" is defined, need "End" and vice versa
|
||||
if ($dhcpsettings{"ROUTER_ADDR_${itf}"}) {
|
||||
if (!(&General::validip($dhcpsettings{"ROUTER_ADDR_${itf}"}))) {
|
||||
$errormessage = "DHCP on ${itf}: " . $Lang::tr{'invalid router address'};
|
||||
goto ERROR;
|
||||
}
|
||||
}
|
||||
if ($dhcpsettings{"START_ADDR_${itf}"}) {
|
||||
if (!(&General::validip($dhcpsettings{"START_ADDR_${itf}"}))) {
|
||||
$errormessage = "DHCP on ${itf}: " . $Lang::tr{'invalid start address'};
|
||||
@@ -571,14 +586,45 @@ foreach my $itf (@ITFs) {
|
||||
|
||||
if ($netsettings{"${itf}_DEV"} ne '' ) { # Show only defined interface
|
||||
my $lc_itf=lc($itf);
|
||||
print <<END
|
||||
my @gwips;
|
||||
my $current_gwip = $dhcpsettings{"ROUTER_ADDR_${itf}"};
|
||||
foreach my $line (@IPFILE) {
|
||||
chomp($line);
|
||||
my @temp = split(/\,/, $line);
|
||||
if ($temp[1] eq $netsettings{"${itf}_DEV"}) {
|
||||
my @tmp = split(/\//, $temp[0]);
|
||||
push(@gwips, $tmp[0]);
|
||||
}
|
||||
}
|
||||
push(@gwips, $netsettings{"${itf}_ADDRESS"}); #add primary ip of $itf/green0 as one of option ip
|
||||
|
||||
print <<END;
|
||||
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td width='25%' class='boldbase'><b><font color='${lc_itf}'>$Lang::tr{"$lc_itf interface"}</font></b></td>
|
||||
<td class='base'>$Lang::tr{'enabled'}
|
||||
<input type='checkbox' name='ENABLE_${itf}' $checked{'ENABLE'}{'on'} /></td>
|
||||
<td width='25%' class='base'>$Lang::tr{'ip address'}<br />$Lang::tr{'netmask'}:</td><td><b>$netsettings{"${itf}_ADDRESS"}<br />$netsettings{"${itf}_NETMASK"}</b></td>
|
||||
</tr><tr>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width='25%' class='base'>$Lang::tr{'router address'} </td>
|
||||
<td>
|
||||
<select name='ROUTER_ADDR_${itf}' id='router_addr' style="width: 200px;">
|
||||
END
|
||||
# display selected, tip from chatgpt
|
||||
foreach my $gwip (@gwips) {
|
||||
my $selected = '';
|
||||
if ($gwip eq $current_gwip ) {
|
||||
$selected = 'selected';
|
||||
}
|
||||
print "<option value=\"$gwip\" $selected>$gwip</option>";
|
||||
}
|
||||
|
||||
print <<END;
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<td width='25%' class='base'>$Lang::tr{'start address'} <img src='/blob.gif' alt='*' /></td>
|
||||
<td width='25%'><input type='text' name='START_ADDR_${itf}' value='$dhcpsettings{"START_ADDR_${itf}"}' /></td>
|
||||
<td width='25%' class='base'>$Lang::tr{'end address'} <img src='/blob.gif' alt='*' /></td>
|
||||
@@ -620,10 +666,9 @@ print <<END
|
||||
</table>
|
||||
<hr />
|
||||
END
|
||||
;
|
||||
}# Show only defined interface
|
||||
}#foreach itf
|
||||
print <<END
|
||||
print <<END;
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td class='base' width='25%'><img src='/blob.gif' align='top' alt='*' /> $Lang::tr{'required field'}</td>
|
||||
@@ -632,7 +677,7 @@ print <<END
|
||||
</tr>
|
||||
</table>
|
||||
END
|
||||
;
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
# DHCP DNS update support (RFC2136)
|
||||
@@ -1321,7 +1366,12 @@ sub buildconf {
|
||||
}
|
||||
print FILE "\toption subnet-mask " . $netsettings{"${itf}_NETMASK"} . ";\n";
|
||||
print FILE "\toption domain-name \"" . $dhcpsettings{"DOMAIN_NAME_${itf}"} . "\";\n";
|
||||
print FILE "\toption routers " . $netsettings{"${itf}_ADDRESS"} . ";\n";
|
||||
if ($dhcpsettings{"ROUTER_ADDR_${itf}"}) {
|
||||
my @temp = split("\/", $dhcpsettings{"ROUTER_ADDR_${itf}"});
|
||||
print FILE "\toption routers " . $temp[0] . ";\n";
|
||||
} else {
|
||||
print FILE "\toption routers " . $netsettings{"${itf}_ADDRESS"} . ";\n";
|
||||
}
|
||||
print FILE "\toption domain-name-servers " . $dhcpsettings{"DNS1_${itf}"} if ($dhcpsettings{"DNS1_${itf}"});
|
||||
print FILE ", " . $dhcpsettings{"DNS2_${itf}"} if ($dhcpsettings{"DNS2_${itf}"});
|
||||
print FILE ";\n" if ($dhcpsettings{"DNS1_${itf}"});
|
||||
|
||||
@@ -127,18 +127,20 @@ if (($cgiparams{'SERVERS'} eq $Lang::tr{'save'}) || ($cgiparams{'SERVERS'} eq $L
|
||||
$errormessage = "$Lang::tr{'invalid ip'}: $cgiparams{'NAMESERVER'}";
|
||||
}
|
||||
|
||||
# Check if a TLS is enabled and no TLS_HOSTNAME has benn specified.
|
||||
elsif($settings{'PROTO'} eq "TLS") {
|
||||
unless($cgiparams{"TLS_HOSTNAME"}) {
|
||||
$errormessage = "$Lang::tr{'dns no tls hostname given'}";
|
||||
} else {
|
||||
# Check if the provided domain is valid.
|
||||
unless(&General::validfqdn($cgiparams{"TLS_HOSTNAME"})) {
|
||||
$errormessage = "$Lang::tr{'invalid ip or hostname'}: $cgiparams{'TLS_HOSTNAME'}";
|
||||
}
|
||||
# Check if the provided hostname is valid
|
||||
if ($cgiparams{'TLS_HOSTNAME'} ne "") {
|
||||
unless (&General::validfqdn($cgiparams{"TLS_HOSTNAME"})) {
|
||||
$errormessage = "$Lang::tr{'invalid ip or hostname'}: " . &Header::escape($cgiparams{'TLS_HOSTNAME'});
|
||||
}
|
||||
}
|
||||
|
||||
# Check if a TLS is enabled and no TLS_HOSTNAME has benn specified.
|
||||
if ($settings{'PROTO'} eq "TLS") {
|
||||
unless ($cgiparams{"TLS_HOSTNAME"}) {
|
||||
$errormessage = "$Lang::tr{'dns no tls hostname given'}";
|
||||
}
|
||||
}
|
||||
|
||||
# Go further if there was no error.
|
||||
if ( ! $errormessage) {
|
||||
# Check if a remark has been entered.
|
||||
@@ -773,9 +775,9 @@ sub show_add_edit_nameserver() {
|
||||
# Check if an ID has been given.
|
||||
if ($cgiparams{'ID'}) {
|
||||
# Assign cgiparams values.
|
||||
$cgiparams{'NAMESERVER'} = $dns_servers{$cgiparams{'ID'}}[0];
|
||||
$cgiparams{'NAMESERVER'} = &Header::escape($dns_servers{$cgiparams{'ID'}}[0]);
|
||||
$cgiparams{'TLS_HOSTNAME'} = $dns_servers{$cgiparams{'ID'}}[1];
|
||||
$cgiparams{'REMARK'} = $dns_servers{$cgiparams{'ID'}}[3];
|
||||
$cgiparams{'REMARK'} = &Header::escape($dns_servers{$cgiparams{'ID'}}[3]);
|
||||
}
|
||||
} else {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'dnsforward add a new entry'});
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2013 Alexander Marx <amarx@ipfire.org> #
|
||||
# Copyright (C) 2013-2025 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2024-2025 BPFire Team <vincent.mc.li@gmail.com> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
@@ -92,6 +93,7 @@ my $configovpn = "${General::swroot}/ovpn/settings";
|
||||
my $fwoptions = "${General::swroot}/optionsfw/settings";
|
||||
my $ifacesettings = "${General::swroot}/ethernet/settings";
|
||||
my $errormessage='';
|
||||
my $maxkey;
|
||||
my $hint='';
|
||||
my $ipgrp="${General::swroot}/outgoing/groups";
|
||||
my $tdcolor='';
|
||||
@@ -129,9 +131,15 @@ print<<END;
|
||||
|
||||
// Check if we are dealing with a protocol, that knows ports.
|
||||
if (\$.inArray(protocol, PROTOCOLS_WITH_PORTS) >= 0) {
|
||||
if (protocol === "TCP") {
|
||||
\$("#XDP_SYNPROXY").show();
|
||||
} else {
|
||||
\$("#XDP_SYNPROXY").hide();
|
||||
}
|
||||
\$("#PROTOCOL_PORTS").show();
|
||||
} else {
|
||||
\$("#PROTOCOL_PORTS").hide();
|
||||
\$("#XDP_SYNPROXY").hide();
|
||||
}
|
||||
|
||||
// Handle ICMP.
|
||||
@@ -214,7 +222,6 @@ if ($fwdfwsettings{'ACTION'} eq 'saverule')
|
||||
&General::readhasharray("$configinput", \%configinputfw);
|
||||
&General::readhasharray("$configoutgoing", \%configoutgoingfw);
|
||||
&General::readhash("/var/ipfire/ethernet/settings", \%netsettings);
|
||||
my $maxkey;
|
||||
#Set Variables according to the JQuery code in protocol section
|
||||
if ($fwdfwsettings{'PROT'} eq 'TCP' || $fwdfwsettings{'PROT'} eq 'UDP')
|
||||
{
|
||||
@@ -298,57 +305,12 @@ if ($fwdfwsettings{'ACTION'} eq 'saverule')
|
||||
$maxkey=&General::findhasharraykey(\%configfwdfw);
|
||||
%rulehash=%configfwdfw;
|
||||
}
|
||||
#check if we have an identical rule already
|
||||
if($fwdfwsettings{'oldrulenumber'} eq $fwdfwsettings{'rulepos'}){
|
||||
foreach my $key (sort keys %rulehash){
|
||||
if ( "$fwdfwsettings{'RULE_ACTION'},$fwdfwsettings{'ACTIVE'},$fwdfwsettings{'grp1'},$fwdfwsettings{$fwdfwsettings{'grp1'}},$fwdfwsettings{'grp2'},$fwdfwsettings{$fwdfwsettings{'grp2'}},$fwdfwsettings{'USE_SRC_PORT'},$fwdfwsettings{'PROT'},$fwdfwsettings{'ICMP_TYPES'},$fwdfwsettings{'SRC_PORT'},$fwdfwsettings{'USESRV'},$fwdfwsettings{'TGT_PROT'},$fwdfwsettings{'ICMP_TGT'},$fwdfwsettings{'grp3'},$fwdfwsettings{$fwdfwsettings{'grp3'}},$fwdfwsettings{'ruleremark'},$fwdfwsettings{'LOG'},$fwdfwsettings{'TIME'},$fwdfwsettings{'TIME_MON'},$fwdfwsettings{'TIME_TUE'},$fwdfwsettings{'TIME_WED'},$fwdfwsettings{'TIME_THU'},$fwdfwsettings{'TIME_FRI'},$fwdfwsettings{'TIME_SAT'},$fwdfwsettings{'TIME_SUN'},$fwdfwsettings{'TIME_FROM'},$fwdfwsettings{'TIME_TO'},$fwdfwsettings{'USE_NAT'},$fwdfwsettings{$fwdfwsettings{'nat'}},$fwdfwsettings{'dnatport'},$fwdfwsettings{'nat'},$fwdfwsettings{'LIMIT_CON_CON'},$fwdfwsettings{'concon'},$fwdfwsettings{'RATE_LIMIT'},$fwdfwsettings{'ratecon'},$fwdfwsettings{'RATETIME'}"
|
||||
eq "$rulehash{$key}[0],$rulehash{$key}[2],$rulehash{$key}[3],$rulehash{$key}[4],$rulehash{$key}[5],$rulehash{$key}[6],$rulehash{$key}[7],$rulehash{$key}[8],$rulehash{$key}[9],$rulehash{$key}[10],$rulehash{$key}[11],$rulehash{$key}[12],$rulehash{$key}[13],$rulehash{$key}[14],$rulehash{$key}[15],$rulehash{$key}[16],$rulehash{$key}[17],$rulehash{$key}[18],$rulehash{$key}[19],$rulehash{$key}[20],$rulehash{$key}[21],$rulehash{$key}[22],$rulehash{$key}[23],$rulehash{$key}[24],$rulehash{$key}[25],$rulehash{$key}[26],$rulehash{$key}[27],$rulehash{$key}[28],$rulehash{$key}[29],$rulehash{$key}[30],$rulehash{$key}[31],$rulehash{$key}[32],$rulehash{$key}[33],$rulehash{$key}[34],$rulehash{$key}[35],$rulehash{$key}[36]"){
|
||||
$errormessage.=$Lang::tr{'fwdfw err ruleexists'};
|
||||
if($fwdfwsettings{'oldruleremark'} ne $fwdfwsettings{'ruleremark'} && $fwdfwsettings{'updatefwrule'} eq 'on' && $fwdfwsettings{'ruleremark'} ne '' && !&validremark($fwdfwsettings{'ruleremark'})){
|
||||
$errormessage=$Lang::tr{'fwdfw err remark'}."<br>";
|
||||
}
|
||||
if($fwdfwsettings{'oldruleremark'} ne $fwdfwsettings{'ruleremark'} && $fwdfwsettings{'updatefwrule'} eq 'on' && $fwdfwsettings{'ruleremark'} ne '' && &validremark($fwdfwsettings{'ruleremark'})){
|
||||
$errormessage='';
|
||||
}
|
||||
if ($fwdfwsettings{'oldruleremark'} eq $fwdfwsettings{'ruleremark'}){
|
||||
$fwdfwsettings{'nosave'} = 'on';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#check Rulepos on new Rule
|
||||
if($fwdfwsettings{'rulepos'} > 0 && !$fwdfwsettings{'oldrulenumber'}){
|
||||
$fwdfwsettings{'oldrulenumber'}=$maxkey;
|
||||
foreach my $key (sort keys %rulehash){
|
||||
if ( "$fwdfwsettings{'RULE_ACTION'},$fwdfwsettings{'ACTIVE'},$fwdfwsettings{'grp1'},$fwdfwsettings{$fwdfwsettings{'grp1'}},$fwdfwsettings{'grp2'},$fwdfwsettings{$fwdfwsettings{'grp2'}},$fwdfwsettings{'USE_SRC_PORT'},$fwdfwsettings{'PROT'},$fwdfwsettings{'ICMP_TYPES'},$fwdfwsettings{'SRC_PORT'},$fwdfwsettings{'USESRV'},$fwdfwsettings{'TGT_PROT'},$fwdfwsettings{'ICMP_TGT'},$fwdfwsettings{'grp3'},$fwdfwsettings{$fwdfwsettings{'grp3'}},$fwdfwsettings{'TIME'},$fwdfwsettings{'TIME_MON'},$fwdfwsettings{'TIME_TUE'},$fwdfwsettings{'TIME_WED'},$fwdfwsettings{'TIME_THU'},$fwdfwsettings{'TIME_FRI'},$fwdfwsettings{'TIME_SAT'},$fwdfwsettings{'TIME_SUN'},$fwdfwsettings{'TIME_FROM'},$fwdfwsettings{'TIME_TO'},$fwdfwsettings{'USE_NAT'},$fwdfwsettings{$fwdfwsettings{'nat'}},$fwdfwsettings{'dnatport'},$fwdfwsettings{'nat'},$fwdfwsettings{'LIMIT_CON_CON'},$fwdfwsettings{'concon'},$fwdfwsettings{'RATE_LIMIT'},$fwdfwsettings{'ratecon'},$fwdfwsettings{'RATETIME'}"
|
||||
eq "$rulehash{$key}[0],$rulehash{$key}[2],$rulehash{$key}[3],$rulehash{$key}[4],$rulehash{$key}[5],$rulehash{$key}[6],$rulehash{$key}[7],$rulehash{$key}[8],$rulehash{$key}[9],$rulehash{$key}[10],$rulehash{$key}[11],$rulehash{$key}[12],$rulehash{$key}[13],$rulehash{$key}[14],$rulehash{$key}[15],$rulehash{$key}[18],$rulehash{$key}[19],$rulehash{$key}[20],$rulehash{$key}[21],$rulehash{$key}[22],$rulehash{$key}[23],$rulehash{$key}[24],$rulehash{$key}[25],$rulehash{$key}[26],$rulehash{$key}[27],$rulehash{$key}[28],$rulehash{$key}[29],$rulehash{$key}[30],$rulehash{$key}[31],$rulehash{$key}[32],$rulehash{$key}[33],$rulehash{$key}[34],$rulehash{$key}[35],$rulehash{$key}[36]"){
|
||||
$errormessage.=$Lang::tr{'fwdfw err ruleexists'};
|
||||
}
|
||||
}
|
||||
}
|
||||
#check if we just close a rule
|
||||
if( $fwdfwsettings{'oldgrp1a'} eq $fwdfwsettings{'grp1'} && $fwdfwsettings{'oldgrp1b'} eq $fwdfwsettings{$fwdfwsettings{'grp1'}} && $fwdfwsettings{'oldgrp2a'} eq $fwdfwsettings{'grp2'} && $fwdfwsettings{'oldgrp2b'} eq $fwdfwsettings{$fwdfwsettings{'grp2'}} && $fwdfwsettings{'oldgrp3a'} eq $fwdfwsettings{'grp3'} && $fwdfwsettings{'oldgrp3b'} eq $fwdfwsettings{$fwdfwsettings{'grp3'}} && $fwdfwsettings{'oldusesrv'} eq $fwdfwsettings{'USESRV'} && $fwdfwsettings{'oldruleremark'} eq $fwdfwsettings{'ruleremark'} && $fwdfwsettings{'oldruletype'} eq $fwdfwsettings{'chain'}){
|
||||
if($fwdfwsettings{'nosave'} eq 'on' && $fwdfwsettings{'updatefwrule'} eq 'on'){
|
||||
$fwdfwsettings{'nosave2'} = 'on';
|
||||
$errormessage='';
|
||||
}
|
||||
}
|
||||
#check max concurrent connections per ip address
|
||||
if ($fwdfwsettings{'LIMIT_CON_CON'} eq 'ON'){
|
||||
if (!($fwdfwsettings{'concon'} =~ /^(\d+)$/)) {
|
||||
$errormessage.=$Lang::tr{'fwdfw err concon'};
|
||||
}
|
||||
}else{
|
||||
$fwdfwsettings{'concon'}='';
|
||||
}
|
||||
#check ratelimit value
|
||||
if ($fwdfwsettings{'RATE_LIMIT'} eq 'ON'){
|
||||
if (!($fwdfwsettings{'ratecon'} =~ /^(\d+)$/)) {
|
||||
$errormessage.=$Lang::tr{'fwdfw err ratecon'};
|
||||
}
|
||||
}else{
|
||||
$fwdfwsettings{'ratecon'}='';
|
||||
}
|
||||
|
||||
&checkrulepos;
|
||||
&checkruleclose;
|
||||
&checkruleconlimit;
|
||||
&checkruleratelimit;
|
||||
|
||||
#increase counters
|
||||
if (!$errormessage){
|
||||
if ($fwdfwsettings{'nosave2'} ne 'on'){
|
||||
@@ -876,8 +838,9 @@ sub checkrule
|
||||
$hint.=$Lang::tr{'fwdfw hint ip2'}." Source: $networkip1/$scidr Target: $networkip2/$tcidr<br>";
|
||||
}
|
||||
}else{
|
||||
|
||||
if ( &General::IpInSubnet($networkip2,$sip,&General::iporsubtodec($scidr)) ){
|
||||
$errormessage.=$Lang::tr{'fwdfw err samesub'};
|
||||
$errormessage.=$Lang::tr{'fwdfw err samesub'} . $fwdfwsettings{'grp1'} .$fwdfwsettings{$fwdfwsettings{'grp1'}} . $fwdfwsettings{'grp2'} . $fwdfwsettings{$fwdfwsettings{'grp2'}};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -959,6 +922,74 @@ sub checkrule
|
||||
$fwdfwsettings{'ICMP_TYPES'}='';
|
||||
}
|
||||
}
|
||||
|
||||
sub checkrulepos
|
||||
{
|
||||
#check if we have an identical rule already
|
||||
if($fwdfwsettings{'oldrulenumber'} eq $fwdfwsettings{'rulepos'}){
|
||||
foreach my $key (sort keys %rulehash){
|
||||
if ( "$fwdfwsettings{'RULE_ACTION'},$fwdfwsettings{'ACTIVE'},$fwdfwsettings{'grp1'},$fwdfwsettings{$fwdfwsettings{'grp1'}},$fwdfwsettings{'grp2'},$fwdfwsettings{$fwdfwsettings{'grp2'}},$fwdfwsettings{'USE_SRC_PORT'},$fwdfwsettings{'PROT'},$fwdfwsettings{'ICMP_TYPES'},$fwdfwsettings{'SRC_PORT'},$fwdfwsettings{'USESRV'},$fwdfwsettings{'TGT_PROT'},$fwdfwsettings{'ICMP_TGT'},$fwdfwsettings{'grp3'},$fwdfwsettings{$fwdfwsettings{'grp3'}},$fwdfwsettings{'ruleremark'},$fwdfwsettings{'LOG'},$fwdfwsettings{'TIME'},$fwdfwsettings{'TIME_MON'},$fwdfwsettings{'TIME_TUE'},$fwdfwsettings{'TIME_WED'},$fwdfwsettings{'TIME_THU'},$fwdfwsettings{'TIME_FRI'},$fwdfwsettings{'TIME_SAT'},$fwdfwsettings{'TIME_SUN'},$fwdfwsettings{'TIME_FROM'},$fwdfwsettings{'TIME_TO'},$fwdfwsettings{'USE_NAT'},$fwdfwsettings{$fwdfwsettings{'nat'}},$fwdfwsettings{'dnatport'},$fwdfwsettings{'nat'},$fwdfwsettings{'LIMIT_CON_CON'},$fwdfwsettings{'concon'},$fwdfwsettings{'RATE_LIMIT'},$fwdfwsettings{'ratecon'},$fwdfwsettings{'RATETIME'},$fwdfwsettings{'USE_SYNPROXY'}"
|
||||
eq "$rulehash{$key}[0],$rulehash{$key}[2],$rulehash{$key}[3],$rulehash{$key}[4],$rulehash{$key}[5],$rulehash{$key}[6],$rulehash{$key}[7],$rulehash{$key}[8],$rulehash{$key}[9],$rulehash{$key}[10],$rulehash{$key}[11],$rulehash{$key}[12],$rulehash{$key}[13],$rulehash{$key}[14],$rulehash{$key}[15],$rulehash{$key}[16],$rulehash{$key}[17],$rulehash{$key}[18],$rulehash{$key}[19],$rulehash{$key}[20],$rulehash{$key}[21],$rulehash{$key}[22],$rulehash{$key}[23],$rulehash{$key}[24],$rulehash{$key}[25],$rulehash{$key}[26],$rulehash{$key}[27],$rulehash{$key}[28],$rulehash{$key}[29],$rulehash{$key}[30],$rulehash{$key}[31],$rulehash{$key}[32],$rulehash{$key}[33],$rulehash{$key}[34],$rulehash{$key}[35],$rulehash{$key}[36],$rulehash{$key}[37]"){
|
||||
$errormessage.=$Lang::tr{'fwdfw err ruleexists'};
|
||||
if($fwdfwsettings{'oldruleremark'} ne $fwdfwsettings{'ruleremark'} && $fwdfwsettings{'updatefwrule'} eq 'on' && $fwdfwsettings{'ruleremark'} ne '' && !&validremark($fwdfwsettings{'ruleremark'})){
|
||||
$errormessage=$Lang::tr{'fwdfw err remark'}."<br>";
|
||||
}
|
||||
if($fwdfwsettings{'oldruleremark'} ne $fwdfwsettings{'ruleremark'} && $fwdfwsettings{'updatefwrule'} eq 'on' && $fwdfwsettings{'ruleremark'} ne '' && &validremark($fwdfwsettings{'ruleremark'})){
|
||||
$errormessage='';
|
||||
}
|
||||
if ($fwdfwsettings{'oldruleremark'} eq $fwdfwsettings{'ruleremark'}){
|
||||
$fwdfwsettings{'nosave'} = 'on';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#check Rulepos on new Rule
|
||||
if($fwdfwsettings{'rulepos'} > 0 && !$fwdfwsettings{'oldrulenumber'}){
|
||||
$fwdfwsettings{'oldrulenumber'}=$maxkey;
|
||||
foreach my $key (sort keys %rulehash){
|
||||
if ( "$fwdfwsettings{'RULE_ACTION'},$fwdfwsettings{'ACTIVE'},$fwdfwsettings{'grp1'},$fwdfwsettings{$fwdfwsettings{'grp1'}},$fwdfwsettings{'grp2'},$fwdfwsettings{$fwdfwsettings{'grp2'}},$fwdfwsettings{'USE_SRC_PORT'},$fwdfwsettings{'PROT'},$fwdfwsettings{'ICMP_TYPES'},$fwdfwsettings{'SRC_PORT'},$fwdfwsettings{'USESRV'},$fwdfwsettings{'TGT_PROT'},$fwdfwsettings{'ICMP_TGT'},$fwdfwsettings{'grp3'},$fwdfwsettings{$fwdfwsettings{'grp3'}},$fwdfwsettings{'TIME'},$fwdfwsettings{'TIME_MON'},$fwdfwsettings{'TIME_TUE'},$fwdfwsettings{'TIME_WED'},$fwdfwsettings{'TIME_THU'},$fwdfwsettings{'TIME_FRI'},$fwdfwsettings{'TIME_SAT'},$fwdfwsettings{'TIME_SUN'},$fwdfwsettings{'TIME_FROM'},$fwdfwsettings{'TIME_TO'},$fwdfwsettings{'USE_NAT'},$fwdfwsettings{$fwdfwsettings{'nat'}},$fwdfwsettings{'dnatport'},$fwdfwsettings{'nat'},$fwdfwsettings{'LIMIT_CON_CON'},$fwdfwsettings{'concon'},$fwdfwsettings{'RATE_LIMIT'},$fwdfwsettings{'ratecon'},$fwdfwsettings{'RATETIME'},$fwdfwsettings{'USE_SYNPROXY'}"
|
||||
eq "$rulehash{$key}[0],$rulehash{$key}[2],$rulehash{$key}[3],$rulehash{$key}[4],$rulehash{$key}[5],$rulehash{$key}[6],$rulehash{$key}[7],$rulehash{$key}[8],$rulehash{$key}[9],$rulehash{$key}[10],$rulehash{$key}[11],$rulehash{$key}[12],$rulehash{$key}[13],$rulehash{$key}[14],$rulehash{$key}[15],$rulehash{$key}[18],$rulehash{$key}[19],$rulehash{$key}[20],$rulehash{$key}[21],$rulehash{$key}[22],$rulehash{$key}[23],$rulehash{$key}[24],$rulehash{$key}[25],$rulehash{$key}[26],$rulehash{$key}[27],$rulehash{$key}[28],$rulehash{$key}[29],$rulehash{$key}[30],$rulehash{$key}[31],$rulehash{$key}[32],$rulehash{$key}[33],$rulehash{$key}[34],$rulehash{$key}[35],$rulehash{$key}[36],$rulehash{$key}[37]"){
|
||||
$errormessage.=$Lang::tr{'fwdfw err ruleexists'};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub checkruleclose
|
||||
{
|
||||
#check if we just close a rule
|
||||
if( $fwdfwsettings{'oldgrp1a'} eq $fwdfwsettings{'grp1'} && $fwdfwsettings{'oldgrp1b'} eq $fwdfwsettings{$fwdfwsettings{'grp1'}} && $fwdfwsettings{'oldgrp2a'} eq $fwdfwsettings{'grp2'} && $fwdfwsettings{'oldgrp2b'} eq $fwdfwsettings{$fwdfwsettings{'grp2'}} && $fwdfwsettings{'oldgrp3a'} eq $fwdfwsettings{'grp3'} && $fwdfwsettings{'oldgrp3b'} eq $fwdfwsettings{$fwdfwsettings{'grp3'}} && $fwdfwsettings{'oldusesrv'} eq $fwdfwsettings{'USESRV'} && $fwdfwsettings{'oldruleremark'} eq $fwdfwsettings{'ruleremark'} && $fwdfwsettings{'oldruletype'} eq $fwdfwsettings{'chain'}){
|
||||
if($fwdfwsettings{'nosave'} eq 'on' && $fwdfwsettings{'updatefwrule'} eq 'on'){
|
||||
$fwdfwsettings{'nosave2'} = 'on';
|
||||
$errormessage='';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub checkruleconlimit
|
||||
{
|
||||
#check max concurrent connections per ip address
|
||||
if ($fwdfwsettings{'LIMIT_CON_CON'} eq 'ON'){
|
||||
if (!($fwdfwsettings{'concon'} =~ /^(\d+)$/)) {
|
||||
$errormessage.=$Lang::tr{'fwdfw err concon'};
|
||||
}
|
||||
}else{
|
||||
$fwdfwsettings{'concon'}='';
|
||||
}
|
||||
}
|
||||
|
||||
sub checkruleratelimit
|
||||
{
|
||||
#check ratelimit value
|
||||
if ($fwdfwsettings{'RATE_LIMIT'} eq 'ON'){
|
||||
if (!($fwdfwsettings{'ratecon'} =~ /^(\d+)$/)) {
|
||||
$errormessage.=$Lang::tr{'fwdfw err ratecon'};
|
||||
}
|
||||
}else{
|
||||
$fwdfwsettings{'ratecon'}='';
|
||||
}
|
||||
}
|
||||
|
||||
sub checkvpn
|
||||
{
|
||||
my $ip=shift;
|
||||
@@ -1179,6 +1210,40 @@ END
|
||||
|
||||
#End left table. start right table (vpn)
|
||||
print"</tr></table></td><td valign='top'><table width='95%' border='0' align='right'><tr>";
|
||||
|
||||
# WireGuard Peers
|
||||
if (%Wireguard::peers || $optionsfw{'SHOWDROPDOWN'} eq 'on') {
|
||||
print <<EOF;
|
||||
<tr>
|
||||
<td>
|
||||
<input type='radio' name='$grp' id='wg_peer_$srctgt' value='wg_peer_$srctgt' $checked{$grp}{'wg_peer_'.$srctgt}>
|
||||
</td>
|
||||
<td nowrap='nowrap' width='16%'>
|
||||
$Lang::tr{'fwhost wg peers'}
|
||||
</td>
|
||||
<td nowrap='nowrap' width='1%' align='right'>
|
||||
<select name='wg_peer_$srctgt' style='width:200px;'>"
|
||||
EOF
|
||||
# Sort peers by name
|
||||
foreach my $key (sort { $Wireguard::peers{$a}[2] cmp $Wireguard::peers{$b}[2] } keys %Wireguard::peers) {
|
||||
# Load the peer
|
||||
my $peer = &Wireguard::load_peer($key);
|
||||
|
||||
# Is this peer selected?
|
||||
my $selected = ($fwdfwsettings{$fwdfwsettings{$grp}} eq $peer->{'NAME'}) ? "selected" : "";
|
||||
|
||||
print <<EOF;
|
||||
<option value="$peer->{'NAME'}" $selected>$peer->{'NAME'}</option>
|
||||
EOF
|
||||
}
|
||||
|
||||
print <<EOF;
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
EOF
|
||||
}
|
||||
|
||||
# CCD networks
|
||||
if( ! -z $configccdnet || $optionsfw{'SHOWDROPDOWN'} eq 'on'){
|
||||
print"<td width='1%'><input type='radio' name='$grp' id='ovpn_net_$srctgt' value='ovpn_net_$srctgt' $checked{$grp}{'ovpn_net_'.$srctgt}></td><td nowrap='nowrap' width='16%'>$Lang::tr{'fwhost ccdnet'}</td><td nowrap='nowrap' width='1%' align='right'><select name='ovpn_net_$srctgt' style='width:200px;'>";
|
||||
@@ -1262,19 +1327,22 @@ sub get_ip
|
||||
if ($fwdfwsettings{$grp} eq $val.'_addr'){
|
||||
($a,$b) = split (/\//, $fwdfwsettings{$fwdfwsettings{$grp}});
|
||||
}elsif($fwdfwsettings{$grp} eq 'std_net_'.$val){
|
||||
if ($fwdfwsettings{$fwdfwsettings{$grp}} =~ /Gr/i){
|
||||
if ($fwdfwsettings{$fwdfwsettings{$grp}} eq "GREEN"){
|
||||
$a=$netsettings{'GREEN_NETADDRESS'};
|
||||
$b=&General::iporsubtocidr($netsettings{'GREEN_NETMASK'});
|
||||
}elsif($fwdfwsettings{$fwdfwsettings{$grp}} =~ /Ora/i){
|
||||
}elsif($fwdfwsettings{$fwdfwsettings{$grp}} eq "ORANGE"){
|
||||
$a=$netsettings{'ORANGE_NETADDRESS'};
|
||||
$b=&General::iporsubtocidr($netsettings{'ORANGE_NETMASK'});
|
||||
}elsif($fwdfwsettings{$fwdfwsettings{$grp}} =~ /Bl/i){
|
||||
}elsif($fwdfwsettings{$fwdfwsettings{$grp}} eq "BLUE"){
|
||||
$a=$netsettings{'BLUE_NETADDRESS'};
|
||||
$b=&General::iporsubtocidr($netsettings{'BLUE_NETMASK'});
|
||||
}elsif($fwdfwsettings{$fwdfwsettings{$grp}} =~ /OpenVPN/i){
|
||||
}elsif($fwdfwsettings{$fwdfwsettings{$grp}} eq "OpenVPN-Dyn"){
|
||||
&General::readhash("$configovpn",\%ovpnsettings);
|
||||
($a,$b) = split (/\//, $ovpnsettings{'DOVPN_SUBNET'});
|
||||
$b=&General::iporsubtocidr($b);
|
||||
# WireGuard
|
||||
}elsif($fwdfwsettings{$fwdfwsettings{$grp}} eq "WGRW") {
|
||||
return $Wireguard::settings{'CLIENT_POOL'};
|
||||
}
|
||||
}elsif($fwdfwsettings{$grp} eq 'cust_net_'.$val){
|
||||
&General::readhasharray("$confignet", \%customnetwork);
|
||||
@@ -1425,6 +1493,9 @@ sub getcolor
|
||||
}elsif ($val eq 'IPsec RW' ){
|
||||
$tdcolor="style='background-color: $Header::colourvpn;color:white;'";
|
||||
return;
|
||||
}elsif ($val eq "WGRW") {
|
||||
$tdcolor="style='background-color: $Header::colourwg; color: white;'";
|
||||
return;
|
||||
}elsif($val =~ /^(.*?)\/(.*?)$/){
|
||||
my ($sip,$scidr) = split ("/",$val);
|
||||
if ( &Header::orange_used() && &General::IpInSubnet($sip,$netsettings{'ORANGE_ADDRESS'},$netsettings{'ORANGE_NETMASK'})){
|
||||
@@ -1491,8 +1562,19 @@ sub getcolor
|
||||
}
|
||||
}
|
||||
}
|
||||
# WireGuard Roadwarrior
|
||||
if ($Wireguard::settings{'CLIENT_POOL'}) {
|
||||
if (&Network::ip_address_in_network($c, $Wireguard::settings{'CLIENT_POOL'})) {
|
||||
$tdcolor="style='background-color: $Header::colourwg; color:white;'";
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#VPN networks
|
||||
if ($nettype eq 'wg_peer_src' || $nettype eq 'wg_peer_tgt'){
|
||||
$tdcolor="style='background-color: $Header::colourwg;color:white;'";
|
||||
return;
|
||||
}
|
||||
if ($nettype eq 'ovpn_n2n_src' || $nettype eq 'ovpn_n2n_tgt' || $nettype eq 'ovpn_net_src' || $nettype eq 'ovpn_net_tgt'|| $nettype eq 'ovpn_host_src' || $nettype eq 'ovpn_host_tgt'){
|
||||
$tdcolor="style='background-color: $Header::colourovpn;color:white;'";
|
||||
return;
|
||||
@@ -1624,6 +1706,7 @@ sub newrule
|
||||
$fwdfwsettings{'RATE_LIMIT'} = $hash{$key}[34];
|
||||
$fwdfwsettings{'ratecon'} = $hash{$key}[35];
|
||||
$fwdfwsettings{'RATETIME'} = $hash{$key}[36];
|
||||
$fwdfwsettings{'USE_SYNPROXY'} = $hash{$key}[37];
|
||||
$checked{'grp1'}{$fwdfwsettings{'grp1'}} = 'CHECKED';
|
||||
$checked{'grp2'}{$fwdfwsettings{'grp2'}} = 'CHECKED';
|
||||
$checked{'grp3'}{$fwdfwsettings{'grp3'}} = 'CHECKED';
|
||||
@@ -1640,6 +1723,7 @@ sub newrule
|
||||
$checked{'TIME_SAT'}{$fwdfwsettings{'TIME_SAT'}} = 'CHECKED';
|
||||
$checked{'TIME_SUN'}{$fwdfwsettings{'TIME_SUN'}} = 'CHECKED';
|
||||
$checked{'USE_NAT'}{$fwdfwsettings{'USE_NAT'}} = 'CHECKED';
|
||||
$checked{'USE_SYNPROXY'}{$fwdfwsettings{'USE_SYNPROXY'}} = 'CHECKED';
|
||||
$checked{'nat'}{$fwdfwsettings{'nat'}} = 'CHECKED';
|
||||
$checked{'LIMIT_CON_CON'}{$fwdfwsettings{'LIMIT_CON_CON'}} = 'CHECKED';
|
||||
$checked{'RATE_LIMIT'}{$fwdfwsettings{'RATE_LIMIT'}} = 'CHECKED';
|
||||
@@ -1661,6 +1745,7 @@ sub newrule
|
||||
$fwdfwsettings{'oldusesrv'}=$fwdfwsettings{'USESRV'};
|
||||
$fwdfwsettings{'oldruleremark'}=$fwdfwsettings{'ruleremark'};
|
||||
$fwdfwsettings{'oldnat'}=$fwdfwsettings{'USE_NAT'};
|
||||
$fwdfwsettings{'oldsynproxy'}=$fwdfwsettings{'USE_SYNPROXY'};
|
||||
$fwdfwsettings{'oldruletype'}=$fwdfwsettings{'chain'};
|
||||
$fwdfwsettings{'oldconcon'}=$fwdfwsettings{'LIMIT_CON_CON'};
|
||||
$fwdfwsettings{'olduseratelimit'}=$fwdfwsettings{'RATE_LIMIT'};
|
||||
@@ -1688,6 +1773,7 @@ sub newrule
|
||||
$fwdfwsettings{'oldusesrv'}=$fwdfwsettings{'USESRV'};
|
||||
$fwdfwsettings{'oldruleremark'}=$fwdfwsettings{'ruleremark'};
|
||||
$fwdfwsettings{'oldnat'}=$fwdfwsettings{'USE_NAT'};
|
||||
$fwdfwsettings{'oldsynproxy'}=$fwdfwsettings{'USE_SYNPROXY'};
|
||||
$fwdfwsettings{'oldconcon'}=$fwdfwsettings{'LIMIT_CON_CON'};
|
||||
#check if manual ip (source) is orange network
|
||||
if ($fwdfwsettings{'grp1'} eq 'src_addr'){
|
||||
@@ -1901,6 +1987,18 @@ END
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table width="40%" border="0" id="XDP_SYNPROXY">
|
||||
<tr>
|
||||
<!-- #USE_SYNPROXY -->
|
||||
<td>
|
||||
$Lang::tr{'fwdfw use synproxy'}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<input type='checkbox' name='USE_SYNPROXY' id='USE_SYNPROXY' value="ON" $checked{'USE_SYNPROXY'}{'ON'}>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table width="100%" border="0" id="PROTOCOL_PORTS">
|
||||
<tr>
|
||||
<!-- #SOURCEPORT -->
|
||||
@@ -2198,6 +2296,7 @@ END
|
||||
<input type='hidden' name='oldruleremark' value='$fwdfwsettings{'oldruleremark'}' />
|
||||
<input type='hidden' name='oldorange' value='$fwdfwsettings{'oldorange'}' />
|
||||
<input type='hidden' name='oldnat' value='$fwdfwsettings{'oldnat'}' />
|
||||
<input type='hidden' name='oldsynproxy' value='$fwdfwsettings{'oldsynproxy'}' />
|
||||
<input type='hidden' name='oldruletype' value='$fwdfwsettings{'oldruletype'}' />
|
||||
<input type='hidden' name='oldconcon' value='$fwdfwsettings{'oldconcon'}' />
|
||||
<input type='hidden' name='ACTION' value='saverule' ></form><form method='post' style='display:inline'><input type='submit' value='$Lang::tr{'fwhost back'}' style='min-width:100px;'><input type='hidden' name='ACTION' value'reset'></td></td>
|
||||
@@ -2302,6 +2401,7 @@ sub saverule
|
||||
$fwdfwsettings{'ruleremark'}=~ s/,/;/g;
|
||||
utf8::decode($fwdfwsettings{'ruleremark'});
|
||||
$fwdfwsettings{'ruleremark'}=&Header::escape($fwdfwsettings{'ruleremark'});
|
||||
$fwdfwsettings{'PROT'}=&Header::escape($fwdfwsettings{'PROT'});
|
||||
if ($fwdfwsettings{'updatefwrule'} ne 'on'){
|
||||
my $key = &General::findhasharraykey ($hash);
|
||||
$$hash{$key}[0] = $fwdfwsettings{'RULE_ACTION'};
|
||||
@@ -2341,6 +2441,7 @@ sub saverule
|
||||
$$hash{$key}[34] = $fwdfwsettings{'RATE_LIMIT'};
|
||||
$$hash{$key}[35] = $fwdfwsettings{'ratecon'};
|
||||
$$hash{$key}[36] = $fwdfwsettings{'RATETIME'};
|
||||
$$hash{$key}[37] = $fwdfwsettings{'USE_SYNPROXY'};
|
||||
&General::writehasharray("$config", $hash);
|
||||
}else{
|
||||
foreach my $key (sort {$a <=> $b} keys %$hash){
|
||||
@@ -2382,6 +2483,7 @@ sub saverule
|
||||
$$hash{$key}[34] = $fwdfwsettings{'RATE_LIMIT'};
|
||||
$$hash{$key}[35] = $fwdfwsettings{'ratecon'};
|
||||
$$hash{$key}[36] = $fwdfwsettings{'RATETIME'};
|
||||
$$hash{$key}[37] = $fwdfwsettings{'USE_SYNPROXY'};
|
||||
last;
|
||||
}
|
||||
}
|
||||
@@ -2529,10 +2631,10 @@ END
|
||||
@tmpsrc=();
|
||||
@tmptgt=();
|
||||
#check if vpn hosts/nets have been deleted
|
||||
if($$hash{$key}[3] =~ /ipsec/i || $$hash{$key}[3] =~ /ovpn/i){
|
||||
if($$hash{$key}[3] =~ /ipsec/i || $$hash{$key}[3] =~ /^wg_/ || $$hash{$key}[3] =~ /ovpn/i){
|
||||
push (@tmpsrc,$$hash{$key}[4]);
|
||||
}
|
||||
if($$hash{$key}[5] =~ /ipsec/i || $$hash{$key}[5] =~ /ovpn/i){
|
||||
if($$hash{$key}[5] =~ /ipsec/i || $$hash{$key}[5] =~ /^wg_/ || $$hash{$key}[5] =~ /ovpn/i){
|
||||
push (@tmptgt,$$hash{$key}[6]);
|
||||
}
|
||||
foreach my $host (@tmpsrc){
|
||||
@@ -2552,6 +2654,10 @@ END
|
||||
if(&fwlib::get_ovpn_host_ip($host,33) eq ''){
|
||||
$coloryellow='on';
|
||||
}
|
||||
}elsif($$hash{$key}[3] eq 'wg_peer_src') {
|
||||
if (!defined &Wireguard::get_peer_by_name($host)) {
|
||||
$coloryellow = 'on';
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach my $host (@tmptgt){
|
||||
@@ -2571,6 +2677,10 @@ END
|
||||
if(&fwlib::get_ovpn_host_ip($host,33) eq ''){
|
||||
$coloryellow='on';
|
||||
}
|
||||
}elsif($$hash{$key}[5] eq 'wg_peer_tgt') {
|
||||
if (!defined &Wireguard::get_peer_by_name($host)) {
|
||||
$coloryellow = 'on';
|
||||
}
|
||||
}
|
||||
}
|
||||
#check if networkgroups or servicegroups are empty
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2013 Alexander Marx <amarx@ipfire.org> #
|
||||
# Copyright (C) 2013-2025 IPFire Team <info@ipfire.org> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
@@ -582,6 +582,13 @@ if ($fwhostsettings{'ACTION'} eq 'savegrp')
|
||||
$fwhostsettings{'grp_name'}='';
|
||||
$fwhostsettings{'remark'}='';
|
||||
}
|
||||
# Fetch the address from a WireGuard Peer
|
||||
if ($fwhostsettings{'grp2'} eq 'wg_peer' && $fwhostsettings{'WG_PEER'} ne ''){
|
||||
@target=$fwhostsettings{'WG_PEER'};
|
||||
$type='wg_peer';
|
||||
}elsif ($fwhostsettings{'grp2'} eq 'wg_peer' && $fwhostsettings{'WG_PEER'} eq ''){
|
||||
$errormessage=$Lang::tr{'fwhost err groupempty'};
|
||||
}
|
||||
#get address from ovpn ccd static net
|
||||
if ($fwhostsettings{'grp2'} eq 'ovpn_net' && $fwhostsettings{'OVPN_CCD_NET'} ne ''){
|
||||
@target=$fwhostsettings{'OVPN_CCD_NET'};
|
||||
@@ -696,6 +703,10 @@ if ($fwhostsettings{'ACTION'} eq 'savelocationgrp')
|
||||
# Check name
|
||||
if (!&validhostname($grp)){$errormessage.=$Lang::tr{'fwhost err name'};}
|
||||
|
||||
unless (&General::validcc($fwhostsettings{'COUNTRY_CODE'})) {
|
||||
$errormessage = $Lang::tr{'fwhost invalid country code'};
|
||||
}
|
||||
|
||||
# Check for existing group name.
|
||||
if (!&checkgroup($grp) && $fwhostsettings{'update'} ne 'on'){
|
||||
$errormessage = $Lang::tr{'fwhost err grpexist'};
|
||||
@@ -707,7 +718,7 @@ if ($fwhostsettings{'ACTION'} eq 'savelocationgrp')
|
||||
}
|
||||
|
||||
if ($fwhostsettings{'update'} eq 'on'){
|
||||
@target=$fwhostsettings{'COUNTRY_CODE'};
|
||||
@target = $fwhostsettings{'COUNTRY_CODE'};
|
||||
$type='Location Group';
|
||||
|
||||
#check if host/net exists in grp
|
||||
@@ -1320,10 +1331,29 @@ sub showmenu {
|
||||
&Header::openbox('100%', 'left',);
|
||||
print "$Lang::tr{'fwhost welcome'}";
|
||||
print<<END;
|
||||
<br><br><table border='0' width='100%'>
|
||||
<tr><td><form method='post'><input type='submit' name='ACTION' value='$Lang::tr{'fwhost newnet'}' ><input type='submit' name='ACTION' value='$Lang::tr{'fwhost newhost'}' ><input type='submit' name='ACTION' value='$Lang::tr{'fwhost newgrp'}' ><input type='submit' name='ACTION' value='$Lang::tr{'fwhost newlocationgrp'}' ></form></td>
|
||||
<td align='right'><form method='post'><input type='submit' name='ACTION' value='$Lang::tr{'fwhost newservice'}' ><input type='submit' name='ACTION' value='$Lang::tr{'fwhost newservicegrp'}' ></form></td></tr>
|
||||
<tr><td colspan='6'></td></tr></table>
|
||||
<br><br>
|
||||
<table border='0' width='100%'>
|
||||
<tr>
|
||||
<td>
|
||||
<form method='post'>
|
||||
<input type='submit' name='ACTION' value='$Lang::tr{'fwhost newnet'}'>
|
||||
<input type='submit' name='ACTION' value='$Lang::tr{'fwhost newhost'}'>
|
||||
<input type='submit' name='ACTION' value='$Lang::tr{'fwhost newgrp'}'>
|
||||
<input type='submit' name='ACTION' value='$Lang::tr{'fwhost newlocationgrp'}'>
|
||||
</form>
|
||||
</td>
|
||||
<td align='right'>
|
||||
<form method='post'>
|
||||
<input type='submit' name='ACTION' value='$Lang::tr{'fwhost newservice'}'>
|
||||
<input type='submit' name='ACTION' value='$Lang::tr{'fwhost newservicegrp'}'>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan='6'>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
END
|
||||
&Header::closebox();
|
||||
|
||||
@@ -1504,6 +1534,34 @@ END
|
||||
print"</table>";
|
||||
#Inner table right
|
||||
print"</td><td align='right' style='vertical-align:top;'><table width='90%' border='0'>";
|
||||
# WireGuard Peers
|
||||
if (%Wireguard::peers) {
|
||||
print <<EOF;
|
||||
<tr>
|
||||
<td style='width:15em;'>
|
||||
<label>
|
||||
<input type='radio' name='grp2' value='wg_peer' $checked{'grp2'}{'wg_peer'}>
|
||||
$Lang::tr{'fwhost wg peers'}
|
||||
</label>
|
||||
</td>
|
||||
<td style='text-align:right;'>
|
||||
<select name='WG_PEER' style='width:16em;'>"
|
||||
EOF
|
||||
|
||||
foreach my $key (sort { $Wireguard::peers{$a}[2] cmp $Wireguard::peers{$b}[2] } keys %Wireguard::peers) {
|
||||
my $peer = &Wireguard::load_peer($key);
|
||||
|
||||
print <<EOF;
|
||||
<option value="$peer->{"NAME"}">$peer->{"NAME"}</option>
|
||||
EOF
|
||||
}
|
||||
|
||||
print <<EOF;
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
EOF
|
||||
}
|
||||
#OVPN networks
|
||||
if (! -z $configccdnet){
|
||||
print<<END;
|
||||
@@ -1725,7 +1783,7 @@ sub addservice
|
||||
{
|
||||
$fwhostsettings{'oldsrvname'} = $fwhostsettings{'SRV_NAME'};
|
||||
$fwhostsettings{'oldsrvport'} = $fwhostsettings{'SRV_PORT'};
|
||||
$fwhostsettings{'oldsrvprot'} = $fwhostsettings{'PROT'};
|
||||
$fwhostsettings{'oldsrvprot'} = &Header::escape($fwhostsettings{'PROT'});
|
||||
$fwhostsettings{'oldsrvicmp'} = $fwhostsettings{'ICMP'};
|
||||
}
|
||||
print<<END;
|
||||
@@ -1898,7 +1956,8 @@ END
|
||||
}
|
||||
my $colnet="$customnetwork{$key}[1]/".&General::subtocidr($customnetwork{$key}[2]);
|
||||
my $netcount=&getnetcount($customnetwork{$key}[0]);
|
||||
print"<td width='20%' $col><form method='post'>$customnetwork{$key}[0]</td><td width='15%' align='center' $col>".&getcolor($colnet)."</td><td width='40%' $col>$customnetwork{$key}[3]</td><td align='center' $col>$netcount x</td>";
|
||||
my $netusedin=&getusedin($customnetwork{$key}[0]);
|
||||
print"<td width='20%' $col><form method='post'>$customnetwork{$key}[0]</td><td width='15%' align='center' $col>".&getcolor($colnet)."</td><td width='40%' $col>$customnetwork{$key}[3]</td><td align='center' $col><span title='$netusedin'>$netcount x</span></td>";
|
||||
print<<END;
|
||||
<td width='1%' $col><input type='image' src='/images/edit.gif' align='middle' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' />
|
||||
<input type='hidden' name='ACTION' value='editnet'>
|
||||
@@ -1954,6 +2013,14 @@ sub getcolor
|
||||
$tdcolor="<font style='color: $Header::colourred;'>$c</font>";
|
||||
return $tdcolor;
|
||||
}
|
||||
|
||||
# WireGuard Roadwarrior
|
||||
if ($Wireguard::settings{'CLIENT_POOL'}) {
|
||||
if (&Network::ip_address_in_network($sip, $Wireguard::settings{'CLIENT_POOL'})) {
|
||||
return "<font style='color: $Header::colourwg;'>$c</font>"
|
||||
}
|
||||
}
|
||||
|
||||
#Check if IP is part of OpenVPN N2N subnet
|
||||
foreach my $key (sort keys %ccdhost){
|
||||
if ($ccdhost{$key}[3] eq 'net'){
|
||||
@@ -2044,8 +2111,10 @@ END
|
||||
$customhost{$key}[4]=~s/\s+//g;
|
||||
my $hostcount=0;
|
||||
$hostcount=&gethostcount($customhost{$key}[0]);
|
||||
print"<td width='20%' $col>$customhost{$key}[0]</td><td width='20%' align='center' $col >".&getcolor($ip)."</td><td width='50%' align='left' $col>$customhost{$key}[3]</td><td align='center' $col>$hostcount x</td>";
|
||||
print<<END;
|
||||
my $hostusedin=&getusedin($customhost{$key}[0]);
|
||||
my $color = &getcolor($ip);
|
||||
print <<END;
|
||||
<td width='20%' $col>$customhost{$key}[0]</td><td width='20%' align='center' $col >$color</td><td width='50%' align='left' $col>$customhost{$key}[3]</td><td align='center' $col><span title="$hostusedin">$hostcount x</span></td>
|
||||
<td width='1%' $col><form method='post'><input type='image' src='/images/edit.gif' align='middle' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' />
|
||||
<input type='hidden' name='ACTION' value='edithost' />
|
||||
<input type='hidden' name='HOSTNAME' value='$customhost{$key}[0]' />
|
||||
@@ -2120,7 +2189,8 @@ sub viewtablegrp
|
||||
print "<br><b><u>$grpname</u></b> ";
|
||||
print " <b>$Lang::tr{'remark'}:</b>  $remark   " if ($remark ne '');
|
||||
my $netgrpcount=&getnetcount($grpname);
|
||||
print "<b>$Lang::tr{'used'}:</b> $netgrpcount x";
|
||||
my $groupusedin=&getusedin($grpname);
|
||||
print "<b>$Lang::tr{'used'}:</b> <span title='$groupusedin'>$netgrpcount x</span>";
|
||||
if($netgrpcount == '0')
|
||||
{
|
||||
print"<form method='post' style='display:inline'><input type='image' src='/images/delete.gif' alt='$Lang::tr{'delete'}' title='$Lang::tr{'delete'}' align='right' /><input type='hidden' name='grp_name' value='$grpname' ><input type='hidden' name='ACTION' value='delgrp'></form>";
|
||||
@@ -2258,8 +2328,8 @@ sub viewtablelocationgrp
|
||||
|
||||
# Get group count.
|
||||
my $locationgrpcount=&getlocationcount($grpname);
|
||||
print "<b>$Lang::tr{'used'}:</b> $locationgrpcount x";
|
||||
|
||||
my $locationusedin=&getlocusedin($grpname);
|
||||
print "<b>$Lang::tr{'used'}:</b> <span title='$locationusedin'>$locationgrpcount x</span>";
|
||||
# Only display delete icon, if the group is not used by a firewall rule.
|
||||
if($locationgrpcount == '0') {
|
||||
print"<form method='post' style='display:inline'>\n";
|
||||
@@ -2401,10 +2471,11 @@ END
|
||||
END
|
||||
#Neuer count
|
||||
$srvcount=&getsrvcount($customservice{$key}[0]);
|
||||
my $serviceusedin=&getsrvusedin($customservice{$key}[0]);
|
||||
if($customservice{$key}[3] eq 'All ICMP-Types'){print $Lang::tr{'fwdfw all icmp'};}
|
||||
elsif($customservice{$key}[3] ne 'BLANK'){print $customservice{$key}[3];}
|
||||
print<<END;
|
||||
</td><td align='center' $col>$srvcount x</td>
|
||||
</td><td align='center' $col><span title='$serviceusedin'>$srvcount x</span></td>
|
||||
<td width='1%' $col><form method='post'><input type='image' src='/images/edit.gif' align='middle' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' /><input type='hidden' name='ACTION' value='editservice' />
|
||||
<input type='hidden' name='SRV_NAME' value='$customservice{$key}[0]' />
|
||||
<input type='hidden' name='SRV_PORT' value='$customservice{$key}[1]' />
|
||||
@@ -2476,7 +2547,8 @@ sub viewtableservicegrp
|
||||
if($count >0){print"</table>";$count=1;}
|
||||
print "<br><b><u>$grpname</u></b> ";
|
||||
print "<b>$Lang::tr{'remark'}:</b> $remark " if ($remark ne '');
|
||||
print " <b>$Lang::tr{'used'}:</b> $grpcount x";
|
||||
my $srvgrpusedin=&getsrvusedin($customservicegrp{$key}[0]);
|
||||
print " <b>$Lang::tr{'used'}:</b> <span title='$srvgrpusedin'>$grpcount x</span>";
|
||||
if($grpcount == '0')
|
||||
{
|
||||
print"<form method='post' style='display:inline'><input type='image' src='/images/delete.gif' alt='$Lang::tr{'delete'}' title='$Lang::tr{'delete'}' align='right' /><input type='hidden' name='SRVGRP_NAME' value='$grpname' ><input type='hidden' name='ACTION' value='delservicegrp'></form>";
|
||||
@@ -2749,6 +2821,106 @@ sub getlocationcount
|
||||
}
|
||||
return $counter;
|
||||
}
|
||||
sub getlocusedin
|
||||
{
|
||||
my $groupname=shift;
|
||||
my $titletext="";
|
||||
|
||||
# Location groups are stored as "group:groupname" in the
|
||||
# firewall settings files.
|
||||
my $searchstring = join(':', "group",$groupname);
|
||||
|
||||
#Count services used in firewall - config
|
||||
my $fwfwtext="";
|
||||
# first set title if found
|
||||
foreach my $key1 (keys %fwfwd) {
|
||||
if($fwfwd{$key1}[4] eq $searchstring){
|
||||
$fwfwtext = "$Lang::tr{'firewall rules'}:";
|
||||
}
|
||||
if($fwfwd{$key1}[6] eq $searchstring){
|
||||
$fwfwtext = "$Lang::tr{'firewall rules'}:";
|
||||
}
|
||||
}
|
||||
# then add rule numbers
|
||||
my @fwfwrules = ();
|
||||
foreach my $key1 (keys %fwfwd) {
|
||||
if($fwfwd{$key1}[4] eq $searchstring){
|
||||
push(@fwfwrules, $key1);
|
||||
}
|
||||
if($fwfwd{$key1}[6] eq $searchstring){
|
||||
push(@fwfwrules, $key1);
|
||||
}
|
||||
}
|
||||
my @fwfwarraysorted = sort { $a <=> $b } @fwfwrules;
|
||||
foreach my $rule (@fwfwarraysorted)
|
||||
{
|
||||
$fwfwtext .= "
- $rule";
|
||||
}
|
||||
#Count services used in firewall - input
|
||||
my $fwintext="";
|
||||
foreach my $key2 (keys %fwinp) {
|
||||
if($fwinp{$key2}[4] eq $searchstring){
|
||||
$fwintext = "$Lang::tr{'incoming firewall access'}:";
|
||||
}
|
||||
if($fwinp{$key2}[6] eq $searchstring){
|
||||
$fwintext = "$Lang::tr{'incoming firewall access'}:";
|
||||
}
|
||||
}
|
||||
my @fwinrules = ();
|
||||
foreach my $key2 (keys %fwinp) {
|
||||
if($fwinp{$key2}[4] eq $searchstring){
|
||||
push(@fwinrules, $key2);
|
||||
}
|
||||
if($fwinp{$key2}[6] eq $searchstring){
|
||||
push(@fwinrules, $key2);
|
||||
}
|
||||
}
|
||||
my @fwinarraysorted = sort { $a <=> $b } @fwinrules;
|
||||
foreach my $rule (@fwinarraysorted)
|
||||
{
|
||||
$fwintext .= "
- $rule";
|
||||
}
|
||||
#Count services used in firewall - outgoing
|
||||
my $fwouttext="";
|
||||
foreach my $key3 (keys %fwout) {
|
||||
if($fwout{$key3}[4] eq $searchstring){
|
||||
$fwouttext = "$Lang::tr{'outgoing firewall access'}:";
|
||||
}
|
||||
if($fwout{$key3}[6] eq $searchstring){
|
||||
$fwouttext = "$Lang::tr{'outgoing firewall access'}:";
|
||||
}
|
||||
}
|
||||
my @fwoutrules = ();
|
||||
foreach my $key3 (keys %fwout) {
|
||||
if($fwout{$key3}[4] eq $searchstring){
|
||||
push(@fwoutrules, $key3);
|
||||
}
|
||||
if($fwout{$key3}[6] eq $searchstring){
|
||||
push(@fwoutrules, $key3);
|
||||
}
|
||||
}
|
||||
my @fwoutarraysorted = sort { $a <=> $b } @fwoutrules;
|
||||
foreach my $rule (@fwoutarraysorted)
|
||||
{
|
||||
$fwouttext .= "
- $rule";
|
||||
}
|
||||
if ($fwfwtext) {
|
||||
$titletext .= "$fwfwtext"
|
||||
}
|
||||
if ($fwintext) {
|
||||
if ($titletext) {
|
||||
$titletext .= "
 "
|
||||
}
|
||||
$titletext .= "$fwintext"
|
||||
}
|
||||
if ($fwouttext) {
|
||||
if ($titletext) {
|
||||
$titletext .= "
 "
|
||||
}
|
||||
$titletext .= "$fwouttext"
|
||||
}
|
||||
return $titletext;
|
||||
}
|
||||
sub getnetcount
|
||||
{
|
||||
my $searchstring=shift;
|
||||
@@ -2788,6 +2960,122 @@ sub getnetcount
|
||||
}
|
||||
return $srvcounter;
|
||||
}
|
||||
sub getusedin
|
||||
{
|
||||
my $searchstring=shift;
|
||||
my $titletext="";
|
||||
my $groups=();
|
||||
my $rules=();
|
||||
|
||||
#Count services used in Network/Host group
|
||||
my $servicegrouptext="";
|
||||
foreach my $key (keys %customgrp) {
|
||||
if($customgrp{$key}[2] eq $searchstring){
|
||||
$servicegrouptext = "$Lang::tr{'fwhost cust grp'}:";
|
||||
}
|
||||
}
|
||||
foreach my $key (keys %customgrp) {
|
||||
if($customgrp{$key}[2] eq $searchstring){
|
||||
$servicegrouptext .= "
- $customgrp{$key}[0]";
|
||||
}
|
||||
}
|
||||
#Count services used in firewall - config
|
||||
my $fwfwtext="";
|
||||
# first set title if found
|
||||
foreach my $key1 (keys %fwfwd) {
|
||||
if($fwfwd{$key1}[4] eq $searchstring){
|
||||
$fwfwtext = "$Lang::tr{'firewall rules'}:";
|
||||
}
|
||||
if($fwfwd{$key1}[6] eq $searchstring){
|
||||
$fwfwtext = "$Lang::tr{'firewall rules'}:";
|
||||
}
|
||||
}
|
||||
# then add rule numbers
|
||||
my @fwfwrules = ();
|
||||
foreach my $key1 (keys %fwfwd) {
|
||||
if($fwfwd{$key1}[4] eq $searchstring){
|
||||
push(@fwfwrules, $key1);
|
||||
}
|
||||
if($fwfwd{$key1}[6] eq $searchstring){
|
||||
push(@fwfwrules, $key1);
|
||||
}
|
||||
}
|
||||
my @fwfwarraysorted = sort { $a <=> $b } @fwfwrules;
|
||||
foreach my $rule (@fwfwarraysorted)
|
||||
{
|
||||
$fwfwtext .= "
- $rule";
|
||||
}
|
||||
#Count services used in firewall - input
|
||||
my $fwintext="";
|
||||
foreach my $key2 (keys %fwinp) {
|
||||
if($fwinp{$key2}[4] eq $searchstring){
|
||||
$fwintext = "$Lang::tr{'incoming firewall access'}:";
|
||||
}
|
||||
if($fwinp{$key2}[6] eq $searchstring){
|
||||
$fwintext = "$Lang::tr{'incoming firewall access'}:";
|
||||
}
|
||||
}
|
||||
my @fwinrules = ();
|
||||
foreach my $key2 (keys %fwinp) {
|
||||
if($fwinp{$key2}[4] eq $searchstring){
|
||||
push(@fwinrules, $key2);
|
||||
}
|
||||
if($fwinp{$key2}[6] eq $searchstring){
|
||||
push(@fwinrules, $key2);
|
||||
}
|
||||
}
|
||||
my @fwinarraysorted = sort { $a <=> $b } @fwinrules;
|
||||
foreach my $rule (@fwinarraysorted)
|
||||
{
|
||||
$fwintext .= "
- $rule";
|
||||
}
|
||||
#Count services used in firewall - outgoing
|
||||
my $fwouttext="";
|
||||
foreach my $key3 (keys %fwout) {
|
||||
if($fwout{$key3}[4] eq $searchstring){
|
||||
$fwouttext = "$Lang::tr{'outgoing firewall access'}:";
|
||||
}
|
||||
if($fwout{$key3}[6] eq $searchstring){
|
||||
$fwouttext = "$Lang::tr{'outgoing firewall access'}:";
|
||||
}
|
||||
}
|
||||
my @fwoutrules = ();
|
||||
foreach my $key3 (keys %fwout) {
|
||||
if($fwout{$key3}[4] eq $searchstring){
|
||||
push(@fwoutrules, $key3);
|
||||
}
|
||||
if($fwout{$key3}[6] eq $searchstring){
|
||||
push(@fwoutrules, $key3);
|
||||
}
|
||||
}
|
||||
my @fwoutarraysorted = sort { $a <=> $b } @fwoutrules;
|
||||
foreach my $rule (@fwoutarraysorted)
|
||||
{
|
||||
$fwouttext .= "
- $rule";
|
||||
}
|
||||
if ($servicegrouptext) {
|
||||
$titletext .= "$servicegrouptext"
|
||||
}
|
||||
if ($fwfwtext) {
|
||||
if ($titletext) {
|
||||
$titletext .= "
 "
|
||||
}
|
||||
$titletext .= "$fwfwtext"
|
||||
}
|
||||
if ($fwintext) {
|
||||
if ($titletext) {
|
||||
$titletext .= "
 "
|
||||
}
|
||||
$titletext .= "$fwintext"
|
||||
}
|
||||
if ($fwouttext) {
|
||||
if ($titletext) {
|
||||
$titletext .= "
 "
|
||||
}
|
||||
$titletext .= "$fwouttext"
|
||||
}
|
||||
return $titletext
|
||||
}
|
||||
sub getsrvcount
|
||||
{
|
||||
my $searchstring=shift;
|
||||
@@ -2818,6 +3106,100 @@ sub getsrvcount
|
||||
}
|
||||
return $srvcounter;
|
||||
}
|
||||
sub getsrvusedin
|
||||
{
|
||||
my $searchstring=shift;
|
||||
my $titletext="";
|
||||
#Count services used in servicegroups
|
||||
my $servicegrouptext="";
|
||||
foreach my $key (keys %customservicegrp) {
|
||||
if($customservicegrp{$key}[2] eq $searchstring){
|
||||
$servicegrouptext = "$Lang::tr{'outgoing firewall access'}:";
|
||||
}
|
||||
}
|
||||
foreach my $key (keys %customservicegrp) {
|
||||
if($customservicegrp{$key}[2] eq $searchstring){
|
||||
$servicegrouptext .= "
- $customservicegrp{$key}[0]";
|
||||
}
|
||||
}
|
||||
my $fwfwtext="";
|
||||
# first set title if found
|
||||
foreach my $key1 (keys %fwfwd) {
|
||||
if($fwfwd{$key1}[15] eq $searchstring){
|
||||
$fwfwtext = "$Lang::tr{'firewall rules'}:";
|
||||
}
|
||||
}
|
||||
# then add rule numbers
|
||||
my @fwfwrules = ();
|
||||
foreach my $key1 (keys %fwfwd) {
|
||||
if($fwfwd{$key1}[15] eq $searchstring){
|
||||
push(@fwfwrules, $key1);
|
||||
}
|
||||
}
|
||||
my @fwfwarraysorted = sort { $a <=> $b } @fwfwrules;
|
||||
foreach my $rule (@fwfwarraysorted)
|
||||
{
|
||||
$fwfwtext .= "
- $rule";
|
||||
}
|
||||
#Count services used in firewall - input
|
||||
my $fwintext="";
|
||||
foreach my $key2 (keys %fwinp) {
|
||||
if($fwinp{$key2}[15] eq $searchstring){
|
||||
$fwintext = "$Lang::tr{'incoming firewall access'}:";
|
||||
}
|
||||
}
|
||||
my @fwinrules = ();
|
||||
foreach my $key2 (keys %fwinp) {
|
||||
if($fwinp{$key2}[15] eq $searchstring){
|
||||
push(@fwinrules, $key2);
|
||||
}
|
||||
}
|
||||
my @fwinarraysorted = sort { $a <=> $b } @fwinrules;
|
||||
foreach my $rule (@fwinarraysorted)
|
||||
{
|
||||
$fwintext .= "
- $rule";
|
||||
}
|
||||
#Count services used in firewall - outgoing
|
||||
my $fwouttext="";
|
||||
foreach my $key3 (keys %fwout) {
|
||||
if($fwout{$key3}[15] eq $searchstring){
|
||||
$fwouttext = "$Lang::tr{'outgoing firewall access'}:";
|
||||
}
|
||||
}
|
||||
my @fwoutrules = ();
|
||||
foreach my $key3 (keys %fwout) {
|
||||
if($fwout{$key3}[15] eq $searchstring){
|
||||
push(@fwoutrules, $key3);
|
||||
}
|
||||
}
|
||||
my @fwoutarraysorted = sort { $a <=> $b } @fwoutrules;
|
||||
foreach my $rule (@fwoutarraysorted)
|
||||
{
|
||||
$fwouttext .= "
- $rule";
|
||||
}
|
||||
if ($servicegrouptext ne '') {
|
||||
$titletext .= "$servicegrouptext";
|
||||
}
|
||||
if ($fwfwtext ne '') {
|
||||
if ($titletext) {
|
||||
$titletext .= "
 ";
|
||||
}
|
||||
$titletext .= "$fwfwtext";
|
||||
}
|
||||
if ($fwintext ne '') {
|
||||
if ($titletext) {
|
||||
$titletext .= "
 ";
|
||||
}
|
||||
$titletext .= "$fwintext";
|
||||
}
|
||||
if ($fwouttext) {
|
||||
if ($titletext ne '') {
|
||||
$titletext .= "
 ";
|
||||
}
|
||||
$titletext .= "$fwouttext";
|
||||
}
|
||||
return $titletext
|
||||
}
|
||||
sub deletefromgrp
|
||||
{
|
||||
my $target=shift;
|
||||
@@ -2960,6 +3342,23 @@ sub getipforgroup
|
||||
&deletefromgrp($name,$configgrp);
|
||||
}
|
||||
|
||||
# WireGuard Peers
|
||||
if ($type eq "wg_peer") {
|
||||
my $peer = &Wireguard::get_peer_by_name($name);
|
||||
|
||||
if (defined $peer) {
|
||||
my @addresses = ();
|
||||
|
||||
if ($peer->{"TYPE"} eq "host") {
|
||||
push(@addresses, @{ $peer->{"CLIENT_ADDRESS"} });
|
||||
} elsif ($peer->{"TYPE"} eq "net") {
|
||||
push(@addresses, @{ $peer->{"REMOTE_SUBNETS"} });
|
||||
}
|
||||
|
||||
return join(", ", @addresses);
|
||||
}
|
||||
}
|
||||
|
||||
#get address from ovpn ccd Net-2-Net
|
||||
if ($type eq 'OpenVPN N-2-N'){
|
||||
foreach my $key (keys %ccdhost) {
|
||||
@@ -3036,6 +3435,9 @@ sub getipforgroup
|
||||
&General::readhash("${General::swroot}/ethernet/settings",\%hash);
|
||||
return $hash{'ORANGE_NETADDRESS'}."/".&Network::convert_netmask2prefix($hash{'ORANGE_NETMASK'}) || $hash{'ORANGE_NETMASK'};
|
||||
}
|
||||
if ($name eq "WGRW") {
|
||||
return $Wireguard::settings{'CLIENT_POOL'};
|
||||
}
|
||||
if ($name eq 'ALL'){
|
||||
return "0.0.0.0/0";
|
||||
}
|
||||
|
||||
289
html/cgi-bin/haproxy.cgi
Normal file
289
html/cgi-bin/haproxy.cgi
Normal file
@@ -0,0 +1,289 @@
|
||||
#!/usr/bin/perl
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2023 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2024 BPFire <vincent.mc.li@gmail.com> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
use strict;
|
||||
use experimental 'smartmatch';
|
||||
|
||||
# enable only the following on debugging purpose
|
||||
#use warnings;
|
||||
#use CGI::Carp 'fatalsToBrowser';
|
||||
|
||||
require '/var/ipfire/general-functions.pl';
|
||||
require "${General::swroot}/lang.pl";
|
||||
require "${General::swroot}/header.pl";
|
||||
#workaround to suppress a warning when a variable is used only once
|
||||
my @dummy = ( ${Header::colouryellow} );
|
||||
undef (@dummy);
|
||||
|
||||
our %hasettings=();
|
||||
our %netsettings=();
|
||||
my %mainsettings=();
|
||||
my %timesettings=();
|
||||
my $setting = "${General::swroot}/haproxy/settings";
|
||||
my $configsetting = "${General::swroot}/haproxy/config";
|
||||
my $loxilbipfile = "${General::swroot}/loxilb/ipconfigfile";
|
||||
# because we need commas in the some data
|
||||
my $errormessage = '';
|
||||
#remove 'ENABLE_HA' from '/var/ipfire/haproxy/settings' as it could affect haproxy running state
|
||||
my @nosaved=('ENABLE_HAPROXY');
|
||||
my %color = ();
|
||||
|
||||
$hasettings{'ENABLE_HAPROXY'} = 'off';
|
||||
|
||||
&Header::showhttpheaders();
|
||||
my @MODE= ('tcp', 'http');
|
||||
|
||||
#Settings1 for the first screen box
|
||||
$hasettings{"mode"} = '';
|
||||
$hasettings{"bind"} = '';
|
||||
|
||||
# Read Ipcop settings
|
||||
&General::readhash("${General::swroot}/ethernet/settings", \%netsettings);
|
||||
&General::readhash("${General::swroot}/main/settings", \%mainsettings);
|
||||
&General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", \%color);
|
||||
|
||||
#Get GUI values
|
||||
&Header::getcgihash(\%hasettings);
|
||||
|
||||
if ($hasettings{'ACTION'} eq $Lang::tr{'enable'})
|
||||
{
|
||||
#remove @nosaved from $hasettings before writehash to 'configsettings' file since 'configsetting' is only for haproxy running state
|
||||
my @nosaved = ("mode", "bind", "ENABLE_HAPROXY");
|
||||
map (delete ($hasettings{$_}) ,(@nosaved));
|
||||
&General::writehash("$configsetting", \%hasettings);
|
||||
if ($hasettings{'ENABLE_HAPROXY'} eq 'on') {
|
||||
&General::system('/usr/bin/touch', "${General::swroot}/haproxy/enable_ha");
|
||||
&General::system('/usr/local/bin/haproxyctrl', 'start');
|
||||
} else {
|
||||
&General::system('/usr/local/bin/haproxyctrl', 'stop');
|
||||
unlink "${General::swroot}/haproxy/enable_ha";
|
||||
}
|
||||
}
|
||||
|
||||
# Check Settings1 first because they are needed by &buildconf
|
||||
if ($hasettings{'ACTION'} eq $Lang::tr{'save'}) {
|
||||
|
||||
if ($hasettings{"mode"} eq '') {
|
||||
$errormessage = "mode" . " is $Lang::tr{'required field'}";
|
||||
goto ERROR;
|
||||
}
|
||||
if ($hasettings{"bind"} eq '') {
|
||||
$errormessage = "bind" . " is $Lang::tr{'required field'}";
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
map (delete ($hasettings{$_}) ,@nosaved,'ACTION','KEY1','KEY2','q'); # Must not be saved
|
||||
&General::writehash($setting, \%hasettings); # Save good settings
|
||||
$hasettings{'ACTION'} = $Lang::tr{'save'}; # create an 'ACTION'
|
||||
map ($hasettings{$_} = '',@nosaved,'KEY1','KEY2'); # and reinit vars to empty
|
||||
&buildconf;
|
||||
ERROR:
|
||||
}
|
||||
|
||||
if ($hasettings{'ACTION'} eq '' ) { # First launch from GUI
|
||||
|
||||
$hasettings{"mode"} = '';
|
||||
$hasettings{"bind"} = '';
|
||||
}
|
||||
|
||||
### START PAGE ###
|
||||
&Header::openpage($Lang::tr{'haproxy configuration'}, 1, $Header::extraHead);
|
||||
&Header::openbigbox('100%', 'left', '', $errormessage);
|
||||
|
||||
if ($errormessage) {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'error messages'});
|
||||
print "<font class='base' color=red>$errormessage </font>\n";
|
||||
&Header::closebox();
|
||||
}
|
||||
|
||||
# Read configuration file.
|
||||
&General::readhash("$configsetting", \%hasettings);
|
||||
|
||||
# Checkbox pre-selection.
|
||||
my $checked;
|
||||
if ($hasettings{'ENABLE_HA'} eq "on") {
|
||||
$checked = "checked='checked'";
|
||||
}
|
||||
|
||||
my $sactive = "<table cellpadding='2' cellspacing='0' bgcolor='${Header::colourred}' width='50%'><tr><td align='center'><b><font color='#FFFFFF'>$Lang::tr{'stopped'}</font></b></td></tr></table>";
|
||||
|
||||
my @status = &General::system_output('/usr/local/bin/haproxyctrl', 'status');
|
||||
|
||||
if (grep(/is running/, @status)){
|
||||
$sactive = "<table cellpadding='2' cellspacing='0' bgcolor='${Header::colourgreen}' width='50%'><tr><td align='center'><b><font color='#FFFFFF'>$Lang::tr{'running'}</font></b></td></tr></table>";
|
||||
}
|
||||
|
||||
&Header::openbox('100%', 'center', $Lang::tr{'haproxy status'});
|
||||
|
||||
print <<END;
|
||||
<table width='100%'>
|
||||
<form method='POST' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<td width='25%'> </td>
|
||||
<td width='25%'> </td>
|
||||
<td width='25%'> </td>
|
||||
<tr><td class='boldbase'>$Lang::tr{'haproxy status'}</td>
|
||||
<td align='left'>$sactive</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan='4'> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width='100%' class='boldbase'>$Lang::tr{'enable'}
|
||||
<td align='left'><input type='checkbox' name='ENABLE_HA' $checked></td>
|
||||
<td align='center'><input type='submit' name='ACTION' value='$Lang::tr{'enable'}'></td>
|
||||
</tr>
|
||||
END
|
||||
|
||||
print "</form> </table>\n";
|
||||
|
||||
&Header::closebox();
|
||||
#
|
||||
|
||||
|
||||
&General::readhash($setting, \%hasettings); # Get saved settings and reset to good if needed
|
||||
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'haproxy config'});
|
||||
print "<form method='post' action='$ENV{'SCRIPT_NAME'}'>";
|
||||
|
||||
my %checked = ();
|
||||
|
||||
print <<END;
|
||||
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td width='25%' class='base'>$Lang::tr{'haproxy mode'} <img src='/blob.gif' alt='*' /></td>
|
||||
<td width='25%'><input type='text' name='mode' value='$hasettings{"mode"}' /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width='25%' class='base'>$Lang::tr{'haproxy bind'} <img src='/blob.gif' alt='*' /></td>
|
||||
<td width='25%'><input type='text' name='bind' value='$hasettings{"bind"}' /></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
<hr />
|
||||
END
|
||||
|
||||
print <<END;
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td class='base' width='25%'><img src='/blob.gif' align='top' alt='*' /> $Lang::tr{'required field'}</td>
|
||||
<td width='40%' align='right'><input type='submit' name='ACTION' value='$Lang::tr{'save'}' /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
END
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::closebigbox();
|
||||
&Header::closepage();
|
||||
|
||||
# Build the configuration file mixing settings, fixed leases and advanced options
|
||||
sub buildconf {
|
||||
open(FILE, ">/${General::swroot}/haproxy/haproxy.cfg") or die "Unable to write haproxy.cfg file";
|
||||
flock(FILE, 2);
|
||||
|
||||
# Global settings
|
||||
print FILE <<EOF;
|
||||
|
||||
global
|
||||
# to have these messages end up in /var/log/haproxy.log you will
|
||||
# need to:
|
||||
#
|
||||
# 1) configure syslog to accept network log events. This is done
|
||||
# by adding the '-r' option to the SYSLOGD_OPTIONS in
|
||||
# /etc/sysconfig/syslog
|
||||
#
|
||||
# 2) configure local2 events to go to the /var/log/haproxy.log
|
||||
# file. A line like the following can be added to
|
||||
# /etc/sysconfig/syslog
|
||||
#
|
||||
# local2.* /var/log/haproxy.log
|
||||
#
|
||||
log 127.0.0.1 local2
|
||||
|
||||
chroot /var/lib/haproxy
|
||||
pidfile /var/run/haproxy.pid
|
||||
maxconn 4000
|
||||
user nobody
|
||||
group nobody
|
||||
daemon
|
||||
|
||||
# turn on stats unix socket
|
||||
stats socket /var/lib/haproxy/stats
|
||||
|
||||
defaults
|
||||
mode http
|
||||
log global
|
||||
option httplog
|
||||
option dontlognull
|
||||
option http-server-close
|
||||
option forwardfor except 127.0.0.0/8
|
||||
option redispatch
|
||||
retries 3
|
||||
timeout http-request 10s
|
||||
timeout queue 1m
|
||||
timeout connect 10s
|
||||
timeout client 1m
|
||||
timeout server 1m
|
||||
timeout http-keep-alive 10s
|
||||
timeout check 10s
|
||||
maxconn 3000
|
||||
EOF
|
||||
|
||||
print FILE <<EOF;
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
# main frontend which proxys to the backends
|
||||
#---------------------------------------------------------------------
|
||||
frontend main
|
||||
bind *:5000
|
||||
acl url_static path_beg -i /static /images /javascript /stylesheets
|
||||
acl url_static path_end -i .jpg .gif .png .css .js
|
||||
|
||||
use_backend static if url_static
|
||||
default_backend app
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
# static backend for serving up images, stylesheets and such
|
||||
#---------------------------------------------------------------------
|
||||
backend static
|
||||
balance roundrobin
|
||||
server static 127.0.0.1:4331 check
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
# round robin balancing between the various backends
|
||||
#---------------------------------------------------------------------
|
||||
backend app
|
||||
balance roundrobin
|
||||
server app1 127.0.0.1:5001 check
|
||||
server app2 127.0.0.1:5002 check
|
||||
server app3 127.0.0.1:5003 check
|
||||
server app4 127.0.0.1:5004 check
|
||||
|
||||
EOF
|
||||
|
||||
close(FILE);
|
||||
|
||||
&General::system_background('/usr/local/bin/haproxyctrl', 'restart');
|
||||
}
|
||||
|
||||
@@ -1404,7 +1404,10 @@ print <<END;
|
||||
<td width='50%'><input type='text' name='IGNORE_ENTRY_ADDRESS' value='$entry_address' size='24' /></td>
|
||||
|
||||
<td width='30%'>$Lang::tr{'remark'}: </td>
|
||||
<td wicth='50%'><input type='text' name=IGNORE_ENTRY_REMARK value='$entry_remark' size='24' /></td>
|
||||
<td>
|
||||
<input type='text' name=IGNORE_ENTRY_REMARK
|
||||
value='@{[ &Header::escape($entry_remark) ]}' size='24' />
|
||||
</td>
|
||||
<td align='center' width='20%'><input type='submit' name='WHITELIST' value='$buttontext' /></td>
|
||||
</tr>
|
||||
</form>
|
||||
|
||||
@@ -30,6 +30,7 @@ use Sort::Naturally;
|
||||
require '/var/ipfire/general-functions.pl';
|
||||
require "${General::swroot}/lang.pl";
|
||||
require "${General::swroot}/header.pl";
|
||||
require "${General::swroot}/wireguard-functions.pl";
|
||||
require "/opt/pakfire/lib/functions.pl";
|
||||
|
||||
my %cgiparams=();
|
||||
@@ -342,7 +343,7 @@ if (&Header::orange_used()) {
|
||||
<a href='/cgi-bin/firewall.cgi' style='color:white'><b>$Lang::tr{'dmz'}</b></a>
|
||||
</td>
|
||||
<td style='width:30%; text-align:center;'>$netsettings{'ORANGE_ADDRESS'}/$sub</td>
|
||||
<td style='width:45%; text-align:center; color:$Header::colourgreen;'>Online</td>
|
||||
<td style='width:45%; text-align:center; color:$Header::colourgreen;'>$Lang::tr{'online'}</td>
|
||||
</tr>
|
||||
END
|
||||
}
|
||||
@@ -354,7 +355,7 @@ print<<END;
|
||||
<a href='/cgi-bin/vpnmain.cgi' style='color:white'><b>$Lang::tr{'ipsec'}</b></a>
|
||||
</td>
|
||||
<td style='width:30%; text-align:center;'></td>
|
||||
<td style='width:45%; text-align:center; color:$Header::colourgreen;'>Online</td>
|
||||
<td style='width:45%; text-align:center; color:$Header::colourgreen;'>$Lang::tr{'online'}</td>
|
||||
</tr>
|
||||
END
|
||||
}
|
||||
@@ -375,10 +376,26 @@ print <<END;
|
||||
<a href='/cgi-bin/ovpnmain.cgi' style='color:white'><b>OpenVPN</b></a>
|
||||
</td>
|
||||
<td style='width:30%; text-align:center;'>$ovpnip</td>
|
||||
<td style='width:45%; text-align:center; color:$Header::colourgreen;'>Online</td>
|
||||
<td style='width:45%; text-align:center; color:$Header::colourgreen;'>$Lang::tr{'online'}</td>
|
||||
</tr>
|
||||
END
|
||||
}
|
||||
}
|
||||
|
||||
# Show WireGuard status
|
||||
if (&Wireguard::is_enabled()) {
|
||||
my $network = $Wireguard::settings{'CLIENT_POOL'};
|
||||
|
||||
print<<END;
|
||||
<tr>
|
||||
<td style='width:25%; text-align:center; background-color:$Header::colourwg;'>
|
||||
<a href='/cgi-bin/wireguard.cgi' style='color:white'><b>$Lang::tr{'wireguard'}</b></a>
|
||||
</td>
|
||||
<td style='width:30%; text-align:center;'>$network</td>
|
||||
<td style='width:45%; text-align:center; color:$Header::colourgreen;'>$Lang::tr{'online'}</td>
|
||||
</tr>
|
||||
END
|
||||
}
|
||||
|
||||
print"</table>";
|
||||
&Header::closebox();
|
||||
|
||||
@@ -536,11 +553,6 @@ END
|
||||
&Header::closebox();
|
||||
}
|
||||
|
||||
# Fireinfo
|
||||
if ( ! -e "/var/ipfire/main/send_profile") {
|
||||
$warnmessage .= "<li><a style='color: white;' href='fireinfo.cgi'>$Lang::tr{'fireinfo please enable'}</a></li>";
|
||||
}
|
||||
|
||||
# EOL architecture
|
||||
my ($sysname, $nodename, $release, $version, $machine) = &POSIX::uname();
|
||||
if ($machine =~ m/^arm/) {
|
||||
@@ -604,11 +616,6 @@ if ($warnmessage) {
|
||||
&Header::closebox();
|
||||
}
|
||||
|
||||
my %coredb = &Pakfire::coredbinfo();
|
||||
if (defined $coredb{'AvailableRelease'}) {
|
||||
print "<br /><br /><br /><a href='pakfire.cgi'>$Lang::tr{'core notice 1'} $coredb{'Release'} $Lang::tr{'core notice 2'} $coredb{'AvailableRelease'} $Lang::tr{'core notice 3'}</a>";
|
||||
}
|
||||
|
||||
if ( -e "/var/run/need_reboot" ) {
|
||||
print "<div style='text-align:center; color:red;'>";
|
||||
print "<br/><br/>$Lang::tr{'needreboot'}!";
|
||||
|
||||
374
html/cgi-bin/keepalived.cgi
Normal file
374
html/cgi-bin/keepalived.cgi
Normal file
@@ -0,0 +1,374 @@
|
||||
#!/usr/bin/perl
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2023 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2024 BPFire <vincent.mc.li@gmail.com> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
use strict;
|
||||
use experimental 'smartmatch';
|
||||
|
||||
# enable only the following on debugging purpose
|
||||
#use warnings;
|
||||
#use CGI::Carp 'fatalsToBrowser';
|
||||
|
||||
require '/var/ipfire/general-functions.pl';
|
||||
require "${General::swroot}/lang.pl";
|
||||
require "${General::swroot}/header.pl";
|
||||
#workaround to suppress a warning when a variable is used only once
|
||||
my @dummy = ( ${Header::colouryellow} );
|
||||
undef (@dummy);
|
||||
|
||||
our %hasettings=();
|
||||
our %netsettings=();
|
||||
my %mainsettings=();
|
||||
my %timesettings=();
|
||||
my $setting = "${General::swroot}/keepalived/settings";
|
||||
my $runsetting = "${General::swroot}/keepalived/runsettings";
|
||||
my $loxilbipfile = "${General::swroot}/loxilb/ipconfigfile";
|
||||
# because we need commas in the some data
|
||||
my $errormessage = '';
|
||||
#remove 'ENABLE_HA' from '/var/ipfire/keepalived/settings' as it could affect keepalived running state
|
||||
my @nosaved=('ENABLE_HA');
|
||||
my %color = ();
|
||||
|
||||
$hasettings{'ENABLE_HA'} = 'off';
|
||||
|
||||
# Load multiline data
|
||||
our @current = ();
|
||||
if (open(FILE, "$loxilbipfile")) {
|
||||
@current = <FILE>;
|
||||
close (FILE);
|
||||
}
|
||||
|
||||
&Header::showhttpheaders();
|
||||
our @ITFs=('RED', 'GREEN');
|
||||
my @STATE= ('MASTER', 'BACKUP');
|
||||
my $DUMMY_IP = '192.0.2.1'; #for HA master/backup state tracking
|
||||
|
||||
#Settings1 for the first screen box
|
||||
foreach my $itf (@ITFs) {
|
||||
$hasettings{"ENABLE_${itf}"} = 'off';
|
||||
$hasettings{"state_${itf}"} = '';
|
||||
$hasettings{"garp_master_delay_${itf}"} = '';
|
||||
$hasettings{"virtual_router_id_${itf}"} = '';
|
||||
$hasettings{"priority_${itf}"} = '';
|
||||
$hasettings{"advert_int_${itf}"} = '';
|
||||
$hasettings{"auth_pass_${itf}"} = '';
|
||||
$hasettings{"unicast_peer_${itf}"} = '';
|
||||
$hasettings{"virtual_ipaddress_${itf}"} = '';
|
||||
}
|
||||
|
||||
# Read Ipcop settings
|
||||
&General::readhash("${General::swroot}/ethernet/settings", \%netsettings);
|
||||
&General::readhash("${General::swroot}/main/settings", \%mainsettings);
|
||||
&General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", \%color);
|
||||
|
||||
#Get GUI values
|
||||
&Header::getcgihash(\%hasettings);
|
||||
|
||||
if ($hasettings{'ACTION'} eq $Lang::tr{'enable'})
|
||||
{
|
||||
#remove @nosaved from $hasettings before writehash to 'runsettings' file since 'runsetting' is only for keepalived running state
|
||||
foreach my $itf (@ITFs) {
|
||||
my @nosaved = ("virtual_router_id_${itf}", "priority_${itf}", "unicast_peer_${itf}", "auth_pass_${itf}", "garp_master_delay_${itf}", "advert_int_${itf}", "virtual_ipaddress_${itf}", "state_${itf}", "ENABLE_${itf}");
|
||||
map (delete ($hasettings{$_}) ,(@nosaved));
|
||||
}
|
||||
&General::writehash("$runsetting", \%hasettings);
|
||||
if ($hasettings{'ENABLE_HA'} eq 'on') {
|
||||
&General::system('/usr/bin/touch', "${General::swroot}/keepalived/enable_ha");
|
||||
&General::system('/usr/local/bin/keepalivedctrl', 'start');
|
||||
} else {
|
||||
&General::system('/usr/local/bin/keepalivedctrl', 'stop');
|
||||
unlink "${General::swroot}/keepalived/enable_ha";
|
||||
}
|
||||
}
|
||||
|
||||
# Check Settings1 first because they are needed by &buildconf
|
||||
if ($hasettings{'ACTION'} eq $Lang::tr{'save'}) {
|
||||
foreach my $itf (@ITFs) {
|
||||
if ($hasettings{"ENABLE_${itf}"} eq 'on' ) {
|
||||
|
||||
if (!(&General::validnum($hasettings{"virtual_router_id_${itf}"})) || ($hasettings{"virtual_router_id_${itf}"} eq '')) {
|
||||
$errormessage = "virtual_router_id" . " is $Lang::tr{'required field'}" . " or not valid num";
|
||||
goto ERROR;
|
||||
}
|
||||
if (!(&General::validnum($hasettings{"priority_${itf}"})) || ($hasettings{"priority_${itf}"} eq '')) {
|
||||
$errormessage = "priority" . " is $Lang::tr{'required field'}" . " or not valid num";
|
||||
goto ERROR;
|
||||
}
|
||||
if (!(&General::validnum($hasettings{"advert_int_${itf}"})) || ($hasettings{"advert_int_${itf}"} eq '')) {
|
||||
$errormessage = "advert_int" . " is $Lang::tr{'required field'}" . " or not valid num";
|
||||
goto ERROR;
|
||||
}
|
||||
if (!(&General::validnum($hasettings{"garp_master_delay_${itf}"})) || ($hasettings{"garp_master_delay_${itf}"} eq '')) {
|
||||
$errormessage = "garp master delay" . " is $Lang::tr{'required field'}" . " or not valid num";
|
||||
goto ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
map (delete ($hasettings{$_}) ,@nosaved,'ACTION','KEY1','KEY2','q'); # Must not be saved
|
||||
&General::writehash($setting, \%hasettings); # Save good settings
|
||||
$hasettings{'ACTION'} = $Lang::tr{'save'}; # create an 'ACTION'
|
||||
map ($hasettings{$_} = '',@nosaved,'KEY1','KEY2'); # and reinit vars to empty
|
||||
&buildconf;
|
||||
ERROR:
|
||||
}
|
||||
|
||||
if ($hasettings{'ACTION'} eq '' ) { # First launch from GUI
|
||||
|
||||
# Set default DHCP values only if blank and disabled
|
||||
foreach my $itf (@ITFs) {
|
||||
if ($hasettings{"ENABLE_${itf}"} ne 'on' ) {
|
||||
$hasettings{"virtual_router_id_${itf}"} = '50';
|
||||
$hasettings{"priority_${itf}"} = '100';
|
||||
$hasettings{"advert_int_${itf}"} = '1';
|
||||
$hasettings{"auth_pass_${itf}"} = '';
|
||||
$hasettings{"unicast_peer_${itf}"} = '';
|
||||
$hasettings{"garp_master_delay_${itf}"} = '10';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
### START PAGE ###
|
||||
&Header::openpage($Lang::tr{'keepalived configuration'}, 1, $Header::extraHead);
|
||||
&Header::openbigbox('100%', 'left', '', $errormessage);
|
||||
|
||||
if ($errormessage) {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'error messages'});
|
||||
print "<font class='base' color=red>$errormessage </font>\n";
|
||||
&Header::closebox();
|
||||
}
|
||||
|
||||
# Read configuration file.
|
||||
&General::readhash("$runsetting", \%hasettings);
|
||||
|
||||
# Checkbox pre-selection.
|
||||
my $checked;
|
||||
if ($hasettings{'ENABLE_HA'} eq "on") {
|
||||
$checked = "checked='checked'";
|
||||
}
|
||||
|
||||
my $hastate = "<table cellpadding='2' cellspacing='0' bgcolor='${Header::colourred}' width='50%'><tr><td align='center'><b><font color='#FFFFFF'>$Lang::tr{'standby'}</font></b></td></tr></table>";
|
||||
|
||||
my @ips = &General::get_ipaddresses_from_interface("green0");
|
||||
|
||||
if (grep { $_ eq $DUMMY_IP } @ips) {
|
||||
$hastate = "<table cellpadding='2' cellspacing='0' bgcolor='${Header::colourgreen}' width='50%'><tr><td align='center'><b><font color='#FFFFFF'>$Lang::tr{'active'}</font></b></td></tr></table>";
|
||||
}
|
||||
|
||||
my $sactive = "<table cellpadding='2' cellspacing='0' bgcolor='${Header::colourred}' width='50%'><tr><td align='center'><b><font color='#FFFFFF'>$Lang::tr{'stopped'}</font></b></td></tr></table>";
|
||||
|
||||
my @status = &General::system_output('/usr/local/bin/keepalivedctrl', 'status');
|
||||
|
||||
if (grep(/is running/, @status)){
|
||||
$sactive = "<table cellpadding='2' cellspacing='0' bgcolor='${Header::colourgreen}' width='50%'><tr><td align='center'><b><font color='#FFFFFF'>$Lang::tr{'running'}</font></b></td></tr></table>";
|
||||
}
|
||||
|
||||
&Header::openbox('100%', 'center', $Lang::tr{'keepalived status'});
|
||||
|
||||
print <<END;
|
||||
<table width='100%'>
|
||||
<form method='POST' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<td width='25%'> </td>
|
||||
<td width='25%'> </td>
|
||||
<td width='25%'> </td>
|
||||
<tr><td class='boldbase'>$Lang::tr{'keepalived status'}</td>
|
||||
<td align='left'>$sactive</td>
|
||||
<td align='center'>$hastate</td>
|
||||
<td align='right'>
|
||||
<input type='submit' value='Refresh'>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan='4'> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width='100%' class='boldbase'>$Lang::tr{'enable'}
|
||||
<td align='left'><input type='checkbox' name='ENABLE_HA' $checked></td>
|
||||
<td align='center'><input type='submit' name='ACTION' value='$Lang::tr{'enable'}'></td>
|
||||
</tr>
|
||||
END
|
||||
|
||||
print "</form> </table>\n";
|
||||
|
||||
&Header::closebox();
|
||||
#
|
||||
|
||||
|
||||
&General::readhash($setting, \%hasettings); # Get saved settings and reset to good if needed
|
||||
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'keepalived config'});
|
||||
print "<form method='post' action='$ENV{'SCRIPT_NAME'}'>";
|
||||
|
||||
foreach my $itf (@ITFs) {
|
||||
my %checked = ();
|
||||
my @vips;
|
||||
my $lc_itf = lc($itf);
|
||||
my $current_state = $hasettings{"state_${itf}"};
|
||||
my @current_vips = split(/\|/, $hasettings{"virtual_ipaddress_${itf}"}); #multi selected value is separated by pipe |
|
||||
|
||||
foreach my $line (@current) {
|
||||
chomp($line);
|
||||
my @temp = split(/\,/, $line);
|
||||
if ($temp[1] eq $netsettings{"${itf}_DEV"}) {
|
||||
push(@vips, $temp[0]);
|
||||
}
|
||||
}
|
||||
$checked{'ENABLE'}{'on'} = ($hasettings{"ENABLE_${itf}"} ne 'on') ? '' : "checked='checked'";
|
||||
|
||||
print <<END;
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td width='25%' class='boldbase'><b><font color='$lc_itf'>$Lang::tr{"$lc_itf interface"}</font></b></td>
|
||||
<td class='base'>$Lang::tr{'enabled'}
|
||||
<input type='checkbox' name='ENABLE_${itf}' $checked{'ENABLE'}{'on'} /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'keepalived state'}: </td>
|
||||
<td>
|
||||
<select name='state_${itf}' id='state' style="width: 95px;">
|
||||
END
|
||||
|
||||
# display selected, tip from chatgpt
|
||||
foreach my $state (@STATE) {
|
||||
my $selected = ($state eq $current_state) ? 'selected' : '';
|
||||
print "<option value=\"$state\" $selected>$state</option>";
|
||||
}
|
||||
|
||||
print <<END;
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width='25%' class='base'>$Lang::tr{'keepalived virtual router id'} <img src='/blob.gif' alt='*' /></td>
|
||||
<td width='25%'><input type='text' name='virtual_router_id_${itf}' value='$hasettings{"virtual_router_id_${itf}"}' /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width='25%' class='base'>$Lang::tr{'keepalived priority'} <img src='/blob.gif' alt='*' /></td>
|
||||
<td width='25%'><input type='text' name='priority_${itf}' value='$hasettings{"priority_${itf}"}' /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width='25%' class='base'>$Lang::tr{'keepalived advert int'} <img src='/blob.gif' alt='*' /></td>
|
||||
<td width='25%'><input type='text' name='advert_int_${itf}' value='$hasettings{"advert_int_${itf}"}' /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width='25%' class='base'>$Lang::tr{'keepalived garp master delay'} </td>
|
||||
<td width='25%'><input type='text' name='garp_master_delay_${itf}' value='$hasettings{"garp_master_delay_${itf}"}' /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width='25%' class='base'>$Lang::tr{'keepalived auth pass'} <img src='/blob.gif' alt='*' /></td>
|
||||
<td width='25%'><input type='text' name='auth_pass_${itf}' value='$hasettings{"auth_pass_${itf}"}' /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width='25%' class='base'>$Lang::tr{'keepalived unicast peer'} <img src='/blob.gif' alt='*' /></td>
|
||||
<td width='25%'><input type='text' name='unicast_peer_${itf}' value='$hasettings{"unicast_peer_${itf}"}' /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'keepalived virtual address'}: <img src='/blob.gif' alt='*' /></td>
|
||||
<td>
|
||||
<select name='virtual_ipaddress_${itf}' id='virtual_ipaddress' style="width: 200px;" multiple>
|
||||
END
|
||||
|
||||
# display selected, tip from chatgpt
|
||||
foreach my $vip (@vips) {
|
||||
my $selected = (grep { $_ eq $vip } @current_vips) ? 'selected' : '';
|
||||
print "<option value=\"$vip\" $selected>$vip</option>";
|
||||
}
|
||||
|
||||
print <<END;
|
||||
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
END
|
||||
} # foreach itf
|
||||
|
||||
print <<END;
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td class='base' width='25%'><img src='/blob.gif' align='top' alt='*' /> $Lang::tr{'required field'}</td>
|
||||
<td width='40%' align='right'><input type='submit' name='ACTION' value='$Lang::tr{'save'}' /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
END
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::closebigbox();
|
||||
&Header::closepage();
|
||||
|
||||
# Build the configuration file mixing settings, fixed leases and advanced options
|
||||
sub buildconf {
|
||||
open(FILE, ">/${General::swroot}/keepalived/keepalived.conf") or die "Unable to write keepalived.conf file";
|
||||
flock(FILE, 2);
|
||||
|
||||
# Global settings
|
||||
print FILE "global_defs {\n";
|
||||
print FILE "\trouter_id BPFire_DEVEL\n";
|
||||
print FILE "}\n";
|
||||
|
||||
print FILE "\n";
|
||||
|
||||
#Subnet range definition
|
||||
foreach my $itf (@ITFs) {
|
||||
my $lc_itf=lc($itf);
|
||||
if ($hasettings{"ENABLE_${itf}"} eq 'on' ){
|
||||
print FILE "vrrp_instance VI_$lc_itf {" . "\n";
|
||||
print FILE "\tstate " . $hasettings{"state_${itf}"} . "\n";
|
||||
print FILE "\tinterface " . $netsettings{"${itf}_DEV"} . "\n";
|
||||
print FILE "\tvirtual_router_id " . $hasettings{"virtual_router_id_${itf}"} . "\n";
|
||||
print FILE "\tpriority " . $hasettings{"priority_${itf}"} . "\n";
|
||||
print FILE "\tadvert_int " . $hasettings{"advert_int_${itf}"} . "\n";
|
||||
print FILE "\tgarp_master_delay " . $hasettings{"garp_master_delay_${itf}"} . "\n";
|
||||
#unicast peer, red0 does not support multicast
|
||||
print FILE "\tunicast_peer {" . "\n";
|
||||
print FILE "\t\t" . $hasettings{"unicast_peer_${itf}"} . "\n";
|
||||
print FILE "\t}" . "\n";
|
||||
# authentication
|
||||
print FILE "\tauthentication {" . "\n";
|
||||
print FILE "\t\tauth_type PASS" . "\n";
|
||||
print FILE "\t\tauth_pass " . $hasettings{"auth_pass_${itf}"} . "\n";
|
||||
print FILE "\t}" . "\n";
|
||||
# virtual ipaddress
|
||||
print FILE "\tvirtual_ipaddress {" . "\n";
|
||||
print FILE "\t\t$DUMMY_IP" . "\n";
|
||||
my @vips = split(/\|/, $hasettings{"virtual_ipaddress_${itf}"});
|
||||
foreach my $ip (@vips) {
|
||||
print FILE "\t\t$ip" . "\n";
|
||||
}
|
||||
print FILE "\t}" . "\n";
|
||||
|
||||
print FILE "} #$itf\n\n";
|
||||
|
||||
&General::system('/usr/bin/touch', "${General::swroot}/keepalived/enable_${lc_itf}");
|
||||
} else {
|
||||
unlink "${General::swroot}/keepalived/enable_${lc_itf}";
|
||||
}
|
||||
}
|
||||
|
||||
close FILE;
|
||||
|
||||
&General::system_background('/usr/local/bin/keepalivedctrl', 'restart');
|
||||
}
|
||||
894
html/cgi-bin/keepalivedvs.cgi
Normal file
894
html/cgi-bin/keepalivedvs.cgi
Normal file
@@ -0,0 +1,894 @@
|
||||
#!/usr/bin/perl
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2013 Alexander Marx <amarx@ipfire.org> #
|
||||
# Copyright (C) 2024 BPFire #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
use strict;
|
||||
|
||||
# enable only the following on debugging purpose
|
||||
#use warnings;
|
||||
|
||||
use Sort::Naturally;
|
||||
use CGI::Carp 'fatalsToBrowser';
|
||||
no warnings 'uninitialized';
|
||||
require '/var/ipfire/general-functions.pl';
|
||||
require '/var/ipfire/network-functions.pl';
|
||||
require "/var/ipfire/location-functions.pl";
|
||||
require "/usr/lib/firewall/firewall-lib.pl";
|
||||
require "${General::swroot}/lang.pl";
|
||||
require "${General::swroot}/header.pl";
|
||||
|
||||
my %hasettings=();
|
||||
my %virtualserver=();
|
||||
my %realserver=();
|
||||
my %icmptypes=();
|
||||
my %color=();
|
||||
my %defaultNetworks=();
|
||||
my %mainsettings=();
|
||||
my %ownnet=();
|
||||
my %fwfwd=();
|
||||
my %fwinp=();
|
||||
my %fwout=();
|
||||
my %netsettings=();
|
||||
my %optionsfw=();
|
||||
|
||||
my $errormessage;
|
||||
my $hint;
|
||||
my $update=0;
|
||||
my $configvs = "${General::swroot}/keepalived/configvs";
|
||||
my $configrs = "${General::swroot}/keepalived/configrs";
|
||||
my $fwoptions = "${General::swroot}/optionsfw/settings";
|
||||
|
||||
unless (-e $configvs) { &General::system("touch", "$configvs"); }
|
||||
unless (-e $configrs) { &General::system("touch", "$configrs"); }
|
||||
|
||||
&General::readhash("${General::swroot}/main/settings", \%mainsettings);
|
||||
&General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", \%color);
|
||||
&General::readhash("${General::swroot}/ethernet/settings", \%ownnet);
|
||||
&General::readhash("/var/ipfire/ethernet/settings", \%netsettings);
|
||||
&General::readhash($fwoptions, \%optionsfw);
|
||||
|
||||
&Header::getcgihash(\%hasettings);
|
||||
&Header::showhttpheaders();
|
||||
&Header::openpage($Lang::tr{'fwhost menu'}, 1, '');
|
||||
&Header::openbigbox('100%', 'center');
|
||||
|
||||
#### JAVA SCRIPT ####
|
||||
print<<END;
|
||||
<script>
|
||||
var PROTOCOLS_WITH_PORTS = ["TCP", "UDP"];
|
||||
var update_protocol = function() {
|
||||
var protocol = \$("#protocol").val();
|
||||
|
||||
if (protocol === undefined)
|
||||
return;
|
||||
|
||||
// Check if we are dealing with a protocol, that knows ports.
|
||||
if (\$.inArray(protocol, PROTOCOLS_WITH_PORTS) >= 0) {
|
||||
\$("#PORT").show();
|
||||
\$("#PROTOKOLL").hide();
|
||||
} else {
|
||||
\$("#PORT").hide();
|
||||
\$("#PROTOKOLL").show();
|
||||
}
|
||||
};
|
||||
|
||||
\$(document).ready(function() {
|
||||
var protocol = \$("#protocol").val();
|
||||
\$("#protocol").change(update_protocol);
|
||||
update_protocol();
|
||||
// Automatically select radio buttons when corresponding
|
||||
// dropdown menu changes.
|
||||
\$("select").change(function() {
|
||||
var id = \$(this).attr("name");
|
||||
\$('#' + id).prop("checked", true);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
END
|
||||
|
||||
## ACTION ####
|
||||
# Update
|
||||
if ($hasettings{'ACTION'} eq 'updatevs' )
|
||||
{
|
||||
&General::readhasharray("$configvs", \%virtualserver);
|
||||
foreach my $key (keys %virtualserver)
|
||||
{
|
||||
if($virtualserver{$key}[0] eq $hasettings{'orgname'})
|
||||
{
|
||||
$hasettings{'orgname'} = $virtualserver{$key}[0];
|
||||
$hasettings{'orgip'} = $virtualserver{$key}[1];
|
||||
$hasettings{'orgsub'} = $virtualserver{$key}[2];
|
||||
$hasettings{'netremark'} = $virtualserver{$key}[3];
|
||||
$hasettings{'count'} = $virtualserver{$key}[4];
|
||||
delete $virtualserver{$key};
|
||||
|
||||
}
|
||||
}
|
||||
&General::writehasharray("$configvs", \%virtualserver);
|
||||
$hasettings{'actualize'} = 'on';
|
||||
$hasettings{'ACTION'} = 'savevs';
|
||||
}
|
||||
if ($hasettings{'ACTION'} eq 'updaters')
|
||||
{
|
||||
my ($ip,$subnet);
|
||||
&General::readhasharray("$configrs", \%realserver);
|
||||
foreach my $key (keys %realserver)
|
||||
{
|
||||
if($realserver{$key}[0] eq $hasettings{'orgname'})
|
||||
{
|
||||
if ($realserver{$key}[1] eq 'ip'){
|
||||
($ip,$subnet) = split (/\//,$realserver{$key}[2]);
|
||||
}else{
|
||||
$ip = $realserver{$key}[2];
|
||||
}
|
||||
$hasettings{'orgip'} = $ip;
|
||||
delete $realserver{$key};
|
||||
&General::writehasharray("$configrs", \%realserver);
|
||||
}
|
||||
}
|
||||
$hasettings{'actualize'} = 'on';
|
||||
if($hasettings{'orgip'}){
|
||||
$hasettings{'ACTION'} = 'savers';
|
||||
}else{
|
||||
$hasettings{'ACTION'} = $Lang::tr{'fwhost newhost'};
|
||||
}
|
||||
}
|
||||
# save
|
||||
if ($hasettings{'ACTION'} eq 'savevs' )
|
||||
{
|
||||
my $needrules=0;
|
||||
if ($hasettings{'orgname'} eq ''){$hasettings{'orgname'}=$hasettings{'HOSTNAME'};}
|
||||
#check if all fields are set
|
||||
if ($hasettings{'HOSTNAME'} eq '' || $hasettings{'IP'} eq '' || $hasettings{'SUBNET'} eq '')
|
||||
{
|
||||
$errormessage=$errormessage.$Lang::tr{'fwhost err empty'};
|
||||
&addvs;
|
||||
&viewtablevs;
|
||||
}else{
|
||||
#convert ip if leading '0' exists
|
||||
$hasettings{'IP'} = &Network::ip_remove_zero($hasettings{'IP'});
|
||||
|
||||
#check valid ip
|
||||
if (!&General::validipandmask($hasettings{'IP'}."/".$hasettings{'SUBNET'}))
|
||||
{
|
||||
$errormessage=$errormessage.$Lang::tr{'fwhost err addr'};
|
||||
$hasettings{'BLK_HOST'} ='readonly';
|
||||
$hasettings{'NOCHECK'} ='false';
|
||||
$hasettings{'error'} ='on';
|
||||
}
|
||||
#check remark
|
||||
if ($hasettings{'NETREMARK'} ne '' && !&validremark($hasettings{'NETREMARK'})){
|
||||
$errormessage=$Lang::tr{'fwhost err remark'};
|
||||
$hasettings{'error'} ='on';
|
||||
}
|
||||
#check if subnet is sigle host
|
||||
if(&General::iporsubtocidr($hasettings{'SUBNET'}) eq '32')
|
||||
{
|
||||
$errormessage=$errormessage.$Lang::tr{'fwhost err sub32'};
|
||||
}
|
||||
if($hasettings{'error'} ne 'on'){
|
||||
my $fullip="$hasettings{'IP'}/".&General::iporsubtocidr($hasettings{'SUBNET'});
|
||||
$errormessage=$errormessage.&General::checksubnets($hasettings{'HOSTNAME'},$fullip,"","exact");
|
||||
}
|
||||
#only check plausi when no error till now
|
||||
if (!$errormessage){
|
||||
&plausicheck("editvs");
|
||||
}
|
||||
if($hasettings{'actualize'} eq 'on' && $hasettings{'newnet'} ne 'on' && $errormessage)
|
||||
{
|
||||
$hasettings{'actualize'} = '';
|
||||
my $key = &General::findhasharraykey (\%virtualserver);
|
||||
foreach my $i (0 .. 3) { $virtualserver{$key}[$i] = "";}
|
||||
$virtualserver{$key}[0] = $hasettings{'orgname'} ;
|
||||
$virtualserver{$key}[1] = $hasettings{'orgip'} ;
|
||||
$virtualserver{$key}[2] = $hasettings{'orgsub'};
|
||||
$virtualserver{$key}[3] = $hasettings{'orgnetremark'};
|
||||
&General::writehasharray("$configvs", \%virtualserver);
|
||||
undef %virtualserver;
|
||||
}
|
||||
if (!$errormessage){
|
||||
&General::readhasharray("$configvs", \%virtualserver);
|
||||
if ($hasettings{'ACTION'} eq 'updatevs'){
|
||||
if ($hasettings{'update'} == '0'){
|
||||
foreach my $key (keys %virtualserver) {
|
||||
if($virtualserver{$key}[0] eq $hasettings{'orgname'}){
|
||||
delete $virtualserver{$key};
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#get count if actualize is 'on'
|
||||
if($hasettings{'actualize'} eq 'on'){
|
||||
$hasettings{'actualize'} = '';
|
||||
#check if we need to reload rules
|
||||
if($hasettings{'orgip'} ne $hasettings{'IP'}){
|
||||
$needrules='on';
|
||||
}
|
||||
if ($hasettings{'orgname'} ne $hasettings{'HOSTNAME'}){
|
||||
}
|
||||
}
|
||||
my $key = &General::findhasharraykey (\%virtualserver);
|
||||
foreach my $i (0 .. 3) { $virtualserver{$key}[$i] = "";}
|
||||
$hasettings{'SUBNET'} = &General::iporsubtocidr($hasettings{'SUBNET'});
|
||||
$virtualserver{$key}[0] = $hasettings{'HOSTNAME'};
|
||||
$virtualserver{$key}[1] = &General::getnetworkip($hasettings{'IP'},$hasettings{'SUBNET'}) ;
|
||||
$virtualserver{$key}[2] = &General::iporsubtodec($hasettings{'SUBNET'}) ;
|
||||
$virtualserver{$key}[3] = $hasettings{'NETREMARK'};
|
||||
&General::writehasharray("$configvs", \%virtualserver);
|
||||
$hasettings{'IP'}=$hasettings{'IP'}."/".&General::iporsubtodec($hasettings{'SUBNET'});
|
||||
undef %virtualserver;
|
||||
$hasettings{'HOSTNAME'}='';
|
||||
$hasettings{'IP'}='';
|
||||
$hasettings{'SUBNET'}='';
|
||||
$hasettings{'NETREMARK'}='';
|
||||
#check if an edited net affected groups and need to reload rules
|
||||
if ($needrules eq 'on'){
|
||||
&General::firewall_config_changed();
|
||||
}
|
||||
&addvs;
|
||||
&viewtablevs;
|
||||
}else{
|
||||
$hasettings{'HOSTNAME'} = $hasettings{'orgname'};
|
||||
&addvs;
|
||||
&viewtablevs;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($hasettings{'ACTION'} eq 'savers')
|
||||
{
|
||||
my $needrules=0;
|
||||
if ($hasettings{'orgname'} eq ''){$hasettings{'orgname'}=$hasettings{'HOSTNAME'};}
|
||||
$hasettings{'SUBNET'}='32';
|
||||
#check if all fields are set
|
||||
if ($hasettings{'HOSTNAME'} eq '' || $hasettings{'IP'} eq '' || $hasettings{'SUBNET'} eq '')
|
||||
{
|
||||
$errormessage=$errormessage.$Lang::tr{'fwhost err empty'};
|
||||
$hasettings{'ACTION'} = 'editrs';
|
||||
}else{
|
||||
if($hasettings{'IP'}=~/^([0-9a-fA-F]{1,2}:){5}[0-9a-fA-F]{1,2}$/){
|
||||
$hasettings{'type'} = 'mac';
|
||||
}elsif($hasettings{'IP'}=~/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/){
|
||||
$hasettings{'type'} = 'ip';
|
||||
}else{
|
||||
$hasettings{'type'} = '';
|
||||
$errormessage=$Lang::tr{'fwhost err ipmac'};
|
||||
}
|
||||
#check remark
|
||||
if ($hasettings{'HOSTREMARK'} ne '' && !&validremark($hasettings{'HOSTREMARK'})){
|
||||
$errormessage=$Lang::tr{'fwhost err remark'};
|
||||
}
|
||||
#CHECK IP-PART
|
||||
if ($hasettings{'type'} eq 'ip'){
|
||||
#convert ip if leading '0' exists
|
||||
$hasettings{'IP'} = &Network::ip_remove_zero($hasettings{'IP'});
|
||||
|
||||
#check for subnet
|
||||
if (rindex($hasettings{'IP'},'/') eq '-1' ){
|
||||
if($hasettings{'type'} eq 'ip' && !&General::validipandmask($hasettings{'IP'}."/32"))
|
||||
{
|
||||
$errormessage.=$errormessage.$Lang::tr{'fwhost err ip'};
|
||||
$hasettings{'error'}='on';
|
||||
}
|
||||
}elsif(rindex($hasettings{'IP'},'/') ne '-1' ){
|
||||
$errormessage=$errormessage.$Lang::tr{'fwhost err ipwithsub'};
|
||||
$hasettings{'error'}='on';
|
||||
}
|
||||
#check if net or broadcast
|
||||
my @tmp= split (/\./,$hasettings{'IP'});
|
||||
if (($tmp[3] eq "0") || ($tmp[3] eq "255")){
|
||||
$errormessage=$Lang::tr{'fwhost err hostip'};
|
||||
}
|
||||
}
|
||||
#only check plausi when no error till now
|
||||
if (!$errormessage){
|
||||
&plausicheck("editrs");
|
||||
}
|
||||
if($hasettings{'actualize'} eq 'on' && $hasettings{'newrs'} ne 'on' && $errormessage){
|
||||
$hasettings{'actualize'} = '';
|
||||
my $key = &General::findhasharraykey (\%realserver);
|
||||
foreach my $i (0 .. 3) { $realserver{$key}[$i] = "";}
|
||||
$realserver{$key}[0] = $hasettings{'orgname'} ;
|
||||
$realserver{$key}[1] = $hasettings{'type'} ;
|
||||
if($realserver{$key}[1] eq 'ip'){
|
||||
$realserver{$key}[2] = $hasettings{'orgip'}."/".&General::iporsubtodec($hasettings{'SUBNET'});
|
||||
}else{
|
||||
$realserver{$key}[2] = $hasettings{'orgip'};
|
||||
}
|
||||
$realserver{$key}[3] = $hasettings{'orgremark'};
|
||||
&General::writehasharray("$configrs", \%realserver);
|
||||
undef %realserver;
|
||||
}
|
||||
if (!$errormessage){
|
||||
#get count if host was edited
|
||||
if($hasettings{'actualize'} eq 'on'){
|
||||
if($hasettings{'orgip'} ne $hasettings{'IP'}){
|
||||
$needrules='on';
|
||||
}
|
||||
if($hasettings{'orgname'} ne $hasettings{'HOSTNAME'}){
|
||||
#check if we need to update firewallrules
|
||||
}
|
||||
}
|
||||
my $key = &General::findhasharraykey (\%realserver);
|
||||
foreach my $i (0 .. 3) { $realserver{$key}[$i] = "";}
|
||||
$realserver{$key}[0] = $hasettings{'HOSTNAME'} ;
|
||||
$realserver{$key}[1] = $hasettings{'type'} ;
|
||||
if ($hasettings{'type'} eq 'ip'){
|
||||
$realserver{$key}[2] = $hasettings{'IP'}."/".&General::iporsubtodec($hasettings{'SUBNET'});
|
||||
}else{
|
||||
$realserver{$key}[2] = $hasettings{'IP'};
|
||||
}
|
||||
$realserver{$key}[3] = $hasettings{'HOSTREMARK'};
|
||||
&General::writehasharray("$configrs", \%realserver);
|
||||
undef %realserver;
|
||||
$hasettings{'HOSTNAME'}='';
|
||||
$hasettings{'IP'}='';
|
||||
$hasettings{'type'}='';
|
||||
$hasettings{'HOSTREMARK'}='';
|
||||
#check if we need to update rules while host was edited
|
||||
if($needrules eq 'on'){
|
||||
&General::firewall_config_changed();
|
||||
}
|
||||
&addrs;
|
||||
&viewtablers;
|
||||
}else{
|
||||
&addrs;
|
||||
&viewtablers;
|
||||
}
|
||||
}
|
||||
}
|
||||
# edit
|
||||
if ($hasettings{'ACTION'} eq 'editvs')
|
||||
{
|
||||
&addvs;
|
||||
&viewtablevs;
|
||||
}
|
||||
if ($hasettings{'ACTION'} eq 'editrs')
|
||||
{
|
||||
&addrs;
|
||||
&viewtablers;
|
||||
}
|
||||
# reset
|
||||
if ($hasettings{'ACTION'} eq 'resetvs')
|
||||
{
|
||||
$hasettings{'HOSTNAME'} ="";
|
||||
$hasettings{'IP'} ="";
|
||||
$hasettings{'SUBNET'} ="";
|
||||
&showmenu;
|
||||
}
|
||||
if ($hasettings{'ACTION'} eq 'resetrs')
|
||||
{
|
||||
$hasettings{'HOSTNAME'} ="";
|
||||
$hasettings{'IP'} ="";
|
||||
$hasettings{'type'} ="";
|
||||
&showmenu;
|
||||
}
|
||||
# delete
|
||||
if ($hasettings{'ACTION'} eq 'delnet')
|
||||
{
|
||||
&General::readhasharray("$configvs", \%virtualserver);
|
||||
foreach my $key (keys %virtualserver) {
|
||||
if($hasettings{'key'} eq $virtualserver{$key}[0]){
|
||||
delete $virtualserver{$key};
|
||||
&General::writehasharray("$configvs", \%virtualserver);
|
||||
last;
|
||||
}
|
||||
}
|
||||
&addvs;
|
||||
&viewtablevs;
|
||||
}
|
||||
if ($hasettings{'ACTION'} eq 'delhost')
|
||||
{
|
||||
&General::readhasharray("$configrs", \%realserver);
|
||||
foreach my $key (keys %realserver) {
|
||||
if($hasettings{'key'} eq $realserver{$key}[0]){
|
||||
delete $realserver{$key};
|
||||
&General::writehasharray("$configrs", \%realserver);
|
||||
last;
|
||||
}
|
||||
}
|
||||
&addrs;
|
||||
&viewtablers;
|
||||
}
|
||||
if ($hasettings{'ACTION'} eq $Lang::tr{'fwhost newnet'})
|
||||
{
|
||||
&addvs;
|
||||
&viewtablevs;
|
||||
}
|
||||
if ($hasettings{'ACTION'} eq $Lang::tr{'fwhost newhost'})
|
||||
{
|
||||
&addrs;
|
||||
&viewtablers;
|
||||
}
|
||||
### VIEW ###
|
||||
if($hasettings{'ACTION'} eq '')
|
||||
{
|
||||
&showmenu;
|
||||
}
|
||||
### FUNCTIONS ###
|
||||
sub showmenu {
|
||||
&Header::openbox('100%', 'left',);
|
||||
print "$Lang::tr{'fwhost welcome'}";
|
||||
print<<END;
|
||||
<br><br><table border='0' width='100%'>
|
||||
<tr><td><form method='post'><input type='submit' name='ACTION' value='$Lang::tr{'fwhost newnet'}' ><input type='submit' name='ACTION' value='$Lang::tr{'fwhost newhost'}' ><input type='submit' name='ACTION' value='$Lang::tr{'fwhost newgrp'}' ><input type='submit' name='ACTION' value='$Lang::tr{'fwhost newlocationgrp'}' ></form></td>
|
||||
<td align='right'><form method='post'><input type='submit' name='ACTION' value='$Lang::tr{'fwhost newservice'}' ><input type='submit' name='ACTION' value='$Lang::tr{'fwhost newservicegrp'}' ></form></td></tr>
|
||||
<tr><td colspan='6'></td></tr></table>
|
||||
END
|
||||
&Header::closebox();
|
||||
|
||||
}
|
||||
# Add
|
||||
sub addvs {
|
||||
&error;
|
||||
&showmenu;
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'fwhost addnet'});
|
||||
$hasettings{'orgname'} = $hasettings{'HOSTNAME'};
|
||||
$hasettings{'orgnetremark'} = $hasettings{'NETREMARK'};
|
||||
|
||||
print <<END;
|
||||
<table border='0' width='100%'>
|
||||
<tr>
|
||||
<td width='15%'>$Lang::tr{'name'}:</td>
|
||||
<td>
|
||||
<form method='post'>
|
||||
<input type='TEXT' name='HOSTNAME' id='textbox1' value='$hasettings{'HOSTNAME'}' $hasettings{'BLK_HOST'} size='20'>
|
||||
<script>document.getElementById('textbox1').focus()</script>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$Lang::tr{'fwhost netaddress'}:</td>
|
||||
<td><input type='TEXT' name='IP' value='$hasettings{'IP'}' $hasettings{'BLK_IP'} size='20' maxlength='15'></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$Lang::tr{'netmask'}:</td>
|
||||
<td><input type='TEXT' name='SUBNET' value='$hasettings{'SUBNET'}' $hasettings{'BLK_IP'} size='20' maxlength='15'></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$Lang::tr{'remark'}:</td>
|
||||
<td><input type='TEXT' name='NETREMARK' value='$hasettings{'NETREMARK'}' style='width: 98.5%;'></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan='6'><br></td>
|
||||
</tr>
|
||||
<tr>
|
||||
END
|
||||
|
||||
if ($hasettings{'ACTION'} eq 'editvs' || $hasettings{'error'} eq 'on') {
|
||||
print <<END;
|
||||
<td colspan='6' align='right'>
|
||||
<input type='submit' value='$Lang::tr{'update'}' style='min-width:100px;'>
|
||||
<input type='hidden' name='ACTION' value='updatevs'>
|
||||
<input type='hidden' name='orgnetremark' value='$hasettings{'orgnetremark'}'>
|
||||
<input type='hidden' name='orgname' value='$hasettings{'orgname'}'>
|
||||
<input type='hidden' name='update' value='on'>
|
||||
<input type='hidden' name='newnet' value='$hasettings{'newnet'}'>
|
||||
</td>
|
||||
</form>
|
||||
END
|
||||
} else {
|
||||
print <<END;
|
||||
<td colspan='6' align='right'>
|
||||
<input type='submit' value='$Lang::tr{'save'}' style='min-width:100px;'>
|
||||
<input type='hidden' name='ACTION' value='savevs'>
|
||||
<input type='hidden' name='newnet' value='on'>
|
||||
</td>
|
||||
</form>
|
||||
END
|
||||
}
|
||||
|
||||
print <<END;
|
||||
<form method='post' style='display:inline'>
|
||||
<input type='submit' value='$Lang::tr{'fwhost back'}' style='min-width:100px;'>
|
||||
<input type='hidden' name='ACTION' value='resetvs'>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
END
|
||||
|
||||
&Header::closebox();
|
||||
}
|
||||
|
||||
sub addrs {
|
||||
&error;
|
||||
&showmenu;
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'fwhost addhost'});
|
||||
|
||||
$hasettings{'orgname'} = $hasettings{'HOSTNAME'};
|
||||
$hasettings{'orgremark'} = $hasettings{'HOSTREMARK'};
|
||||
|
||||
print <<END;
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td>$Lang::tr{'name'}:</td>
|
||||
<td>
|
||||
<form method='post' style='display:inline;'>
|
||||
<input type='TEXT' name='HOSTNAME' id='textbox1' value='$hasettings{'HOSTNAME'}' $hasettings{'BLK_HOST'} size='20'>
|
||||
<script>document.getElementById('textbox1').focus()</script>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>IP/MAC:</td>
|
||||
<td><input type='TEXT' name='IP' value='$hasettings{'IP'}' $hasettings{'BLK_IP'} size='20' maxlength='17'></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width='10%'>$Lang::tr{'remark'}:</td>
|
||||
<td><input type='TEXT' name='HOSTREMARK' value='$hasettings{'HOSTREMARK'}' style='width:98%;'></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan='5'><br></td>
|
||||
</tr>
|
||||
<tr>
|
||||
END
|
||||
|
||||
if ($hasettings{'ACTION'} eq 'editrs' || $hasettings{'error'} eq 'on') {
|
||||
print <<END;
|
||||
<td colspan='4' align='right'>
|
||||
<input type='submit' value='$Lang::tr{'update'}' style='min-width:100px;'/>
|
||||
<input type='hidden' name='ACTION' value='updaters'>
|
||||
<input type='hidden' name='orgremark' value='$hasettings{'orgremark'}'>
|
||||
<input type='hidden' name='orgname' value='$hasettings{'orgname'}'>
|
||||
<input type='hidden' name='update' value='on'>
|
||||
<input type='hidden' name='newrs' value='$hasettings{'newrs'}'>
|
||||
</form>
|
||||
END
|
||||
} else {
|
||||
print <<END;
|
||||
<td colspan='4' align='right'>
|
||||
<input type='submit' name='savers' value='$Lang::tr{'save'}' style='min-width:100px;'/>
|
||||
<input type='hidden' name='ACTION' value='savers'/>
|
||||
<input type='hidden' name='newrs' value='on'>
|
||||
</form>
|
||||
END
|
||||
}
|
||||
|
||||
print <<END;
|
||||
<form method='post' style='display:inline'>
|
||||
<input type='submit' value='$Lang::tr{'fwhost back'}' style='min-width:100px;'/>
|
||||
<input type='hidden' name='ACTION' value='resetrs'>
|
||||
</form></td>
|
||||
</tr>
|
||||
</table>
|
||||
END
|
||||
|
||||
&Header::closebox();
|
||||
}
|
||||
|
||||
# View
|
||||
|
||||
sub viewtablers {
|
||||
if (!-z $configrs) {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'fwhost cust addr'});
|
||||
&General::readhasharray("$configrs", \%realserver);
|
||||
|
||||
if (!keys %realserver) {
|
||||
print "<center><b>$Lang::tr{'fwhost empty'}</b>";
|
||||
} else {
|
||||
print <<END;
|
||||
<table width='100%' cellspacing='0' class='tbl'>
|
||||
<tr>
|
||||
<th align='center'><b>$Lang::tr{'name'}</b></th>
|
||||
<th align='center'><b>$Lang::tr{'fwhost ip_mac'}</b></th>
|
||||
<th align='center'><b>$Lang::tr{'remark'}</b></th>
|
||||
<th></th>
|
||||
<th width='3%'></th>
|
||||
</tr>
|
||||
END
|
||||
}
|
||||
|
||||
my $count = 0;
|
||||
my $col = '';
|
||||
|
||||
foreach my $key (sort { ncmp($realserver{$a}[0], $realserver{$b}[0]) } keys %realserver) {
|
||||
if (($hasettings{'ACTION'} eq 'editrs' || $hasettings{'error'}) && $hasettings{'HOSTNAME'} eq $realserver{$key}[0]) {
|
||||
print "<tr>";
|
||||
$col = "bgcolor='${Header::colouryellow}'";
|
||||
} elsif ($count % 2) {
|
||||
print "<tr>";
|
||||
$col = "bgcolor='$color{'color20'}'";
|
||||
} else {
|
||||
$col = "bgcolor='$color{'color22'}'";
|
||||
print "<tr>";
|
||||
}
|
||||
|
||||
my ($ip, $sub) = split(/\//, $realserver{$key}[2]);
|
||||
|
||||
print "<td width='20%' align='center' $col>$realserver{$key}[0]</td>";
|
||||
print "<td width='20%' align='center' $col>" . &getcolor($ip) . "</td>";
|
||||
print "<td width='50%' align='center' $col>$realserver{$key}[3]</td>";
|
||||
|
||||
print <<END;
|
||||
<td width='1%' $col>
|
||||
<form method='post'>
|
||||
<input type='image' src='/images/edit.gif' align='middle' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' />
|
||||
<input type='hidden' name='ACTION' value='editrs' />
|
||||
<input type='hidden' name='HOSTNAME' value='$realserver{$key}[0]' />
|
||||
<input type='hidden' name='IP' value='$ip' />
|
||||
<input type='hidden' name='type' value='$realserver{$key}[1]' />
|
||||
<input type='hidden' name='HOSTREMARK' value='$realserver{$key}[3]' />
|
||||
</form>
|
||||
</td>
|
||||
END
|
||||
|
||||
print "<td width='1%' $col><form method='post'>";
|
||||
print "<input type='image' src='/images/delete.gif' align='middle' alt='$Lang::tr{'delete'}' title='$Lang::tr{'delete'}' />";
|
||||
print "<input type='hidden' name='ACTION' value='delhost' />";
|
||||
print "<input type='hidden' name='key' value='$realserver{$key}[0]' />";
|
||||
print "</form></td></tr>";
|
||||
|
||||
$count++;
|
||||
}
|
||||
|
||||
print "</table>";
|
||||
&Header::closebox();
|
||||
}
|
||||
}
|
||||
|
||||
sub viewtablevs {
|
||||
if (!-z $configvs) {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'fwhost cust net'});
|
||||
&General::readhasharray("$configvs", \%virtualserver);
|
||||
|
||||
if (!keys %virtualserver) {
|
||||
print "<center><b>$Lang::tr{'fwhost empty'}</b>";
|
||||
} else {
|
||||
print <<END;
|
||||
<table width='100%' cellspacing='0' class='tbl'>
|
||||
<tr>
|
||||
<th align='center'><b>$Lang::tr{'name'}</b></th>
|
||||
<th align='center'><b>$Lang::tr{'fwhost netaddress'}</b></th>
|
||||
<th align='center'><b>$Lang::tr{'remark'}</b></th>
|
||||
<th></th>
|
||||
<th width='3%'></th>
|
||||
</tr>
|
||||
END
|
||||
}
|
||||
|
||||
my $count = 0;
|
||||
my $col = '';
|
||||
|
||||
foreach my $key (sort { ncmp($a, $b) } keys %virtualserver) {
|
||||
if ($hasettings{'ACTION'} eq 'editvs' && $hasettings{'HOSTNAME'} eq $virtualserver{$key}[0]) {
|
||||
print " <tr>";
|
||||
$col = "bgcolor='${Header::colouryellow}'";
|
||||
} elsif ($count % 2) {
|
||||
$col = "bgcolor='$color{'color20'}'";
|
||||
print " <tr>";
|
||||
} else {
|
||||
$col = "bgcolor='$color{'color22'}'";
|
||||
print " <tr>";
|
||||
}
|
||||
|
||||
my $colnet = "$virtualserver{$key}[1]/" . &General::subtocidr($virtualserver{$key}[2]);
|
||||
|
||||
print "<td width='20%' align='center' $col><form method='post'>$virtualserver{$key}[0]</td>";
|
||||
print "<td width='15%' align='center' $col>" . &getcolor($colnet) . "</td>";
|
||||
print "<td width='40%' align='center' $col>$virtualserver{$key}[3]</td>";
|
||||
|
||||
print <<END;
|
||||
<td width='1%' $col>
|
||||
<input type='image' src='/images/edit.gif' align='middle' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' />
|
||||
<input type='hidden' name='ACTION' value='editvs' />
|
||||
<input type='hidden' name='HOSTNAME' value='$virtualserver{$key}[0]' />
|
||||
<input type='hidden' name='IP' value='$virtualserver{$key}[1]' />
|
||||
<input type='hidden' name='SUBNET' value='$virtualserver{$key}[2]' />
|
||||
<input type='hidden' name='NETREMARK' value='$virtualserver{$key}[3]' />
|
||||
</td></form>
|
||||
END
|
||||
|
||||
print "<td width='1%' $col><form method='post'>";
|
||||
print "<input type='image' src='/images/delete.gif' align='middle' alt='$Lang::tr{'delete'}' title='$Lang::tr{'delete'}' />";
|
||||
print "<input type='hidden' name='ACTION' value='delnet' />";
|
||||
print "<input type='hidden' name='key' value='$virtualserver{$key}[0]' />";
|
||||
print "</form></td></tr>";
|
||||
|
||||
$count++;
|
||||
}
|
||||
|
||||
print "</table>";
|
||||
&Header::closebox();
|
||||
}
|
||||
}
|
||||
|
||||
sub getcolor
|
||||
{
|
||||
my $c=shift;
|
||||
my $sip;
|
||||
my $scidr;
|
||||
my $tdcolor='';
|
||||
#Check if MAC
|
||||
if (&General::validmac($c)){ return $c;}
|
||||
|
||||
#Check if we got a full IP with subnet then split it
|
||||
if($c =~ /^(.*?)\/(.*?)$/){
|
||||
($sip,$scidr) = split ("/",$c);
|
||||
}else{
|
||||
$sip=$c;
|
||||
}
|
||||
|
||||
#Now check if IP is part of ORANGE,BLUE or GREEN
|
||||
if ( &Header::orange_used() && &General::IpInSubnet($sip,$netsettings{'ORANGE_ADDRESS'},$netsettings{'ORANGE_NETMASK'})){
|
||||
$tdcolor="<font style='color: $Header::colourorange;'>$c</font>";
|
||||
return $tdcolor;
|
||||
}
|
||||
if ( &General::IpInSubnet($sip,$netsettings{'GREEN_ADDRESS'},$netsettings{'GREEN_NETMASK'})){
|
||||
$tdcolor="<font style='color: $Header::colourgreen;'>$c</font>";
|
||||
return $tdcolor;
|
||||
}
|
||||
if ( &Header::blue_used() && &General::IpInSubnet($sip,$netsettings{'BLUE_ADDRESS'},$netsettings{'BLUE_NETMASK'})){
|
||||
$tdcolor="<font style='color: $Header::colourblue;'>$c</font>";
|
||||
return $tdcolor;
|
||||
}
|
||||
if ("$sip/$scidr" eq "0.0.0.0/0"){
|
||||
$tdcolor="<font style='color: $Header::colourred;'>$c</font>";
|
||||
return $tdcolor;
|
||||
}
|
||||
|
||||
return "$c";
|
||||
}
|
||||
|
||||
|
||||
sub checkname
|
||||
{
|
||||
my %hash=%{(shift)};
|
||||
foreach my $key (keys %hash) {
|
||||
if($hash{$key}[0] eq $hasettings{'HOSTNAME'}){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
sub checkip
|
||||
{
|
||||
|
||||
my %hash=%{(shift)};
|
||||
my $a=shift;
|
||||
foreach my $key (keys %hash) {
|
||||
if($hash{$key}[$a] eq $hasettings{'IP'}."/".&General::iporsubtodec($hasettings{'SUBNET'})){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
sub error
|
||||
{
|
||||
if ($errormessage) {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'error messages'});
|
||||
print "<class name='base'>$errormessage\n";
|
||||
print " </class>\n";
|
||||
&Header::closebox();
|
||||
}
|
||||
}
|
||||
sub hint
|
||||
{
|
||||
if ($hint) {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'fwhost hint'});
|
||||
print "<class name='base'>$hint\n";
|
||||
print " </class>\n";
|
||||
&Header::closebox();
|
||||
}
|
||||
}
|
||||
sub get_name
|
||||
{
|
||||
my $val=shift;
|
||||
&General::setup_default_networks(\%defaultNetworks);
|
||||
foreach my $network (sort keys %defaultNetworks)
|
||||
{
|
||||
return "$network" if ($val eq $defaultNetworks{$network}{'NAME'});
|
||||
}
|
||||
}
|
||||
sub gethostcount
|
||||
{
|
||||
my $searchstring=shift;
|
||||
}
|
||||
sub getnetcount
|
||||
{
|
||||
my $searchstring=shift;
|
||||
}
|
||||
sub plausicheck
|
||||
{
|
||||
my $edit=shift;
|
||||
#check hostname
|
||||
if (!&validhostname($hasettings{'HOSTNAME'}))
|
||||
{
|
||||
$errormessage=$errormessage.$Lang::tr{'fwhost err name'};
|
||||
$hasettings{'BLK_IP'}='readonly';
|
||||
$hasettings{'HOSTNAME'} = $hasettings{'orgname'};
|
||||
if ($hasettings{'update'} eq 'on'){$hasettings{'ACTION'}=$edit;}
|
||||
}
|
||||
#check if network with this name already exists
|
||||
&General::readhasharray("$configvs", \%virtualserver);
|
||||
if (!&checkname(\%virtualserver))
|
||||
{
|
||||
$errormessage=$errormessage."<br>".$Lang::tr{'fwhost err netexist'};
|
||||
$hasettings{'HOSTNAME'} = $hasettings{'orgname'};
|
||||
if ($hasettings{'update'} eq 'on'){$hasettings{'ACTION'}=$edit;}
|
||||
}
|
||||
#check if network ip already exists
|
||||
if (!&checkip(\%virtualserver,1))
|
||||
{
|
||||
$errormessage=$errormessage."<br>".$Lang::tr{'fwhost err net'};
|
||||
if ($hasettings{'update'} eq 'on'){$hasettings{'ACTION'}=$edit;}
|
||||
}
|
||||
#check if host with this name already exists
|
||||
&General::readhasharray("$configrs", \%realserver);
|
||||
if (!&checkname(\%realserver))
|
||||
{
|
||||
$errormessage.="<br>".$Lang::tr{'fwhost err hostexist'};
|
||||
$hasettings{'HOSTNAME'} = $hasettings{'orgname'};
|
||||
if ($hasettings{'update'} eq 'on'){$hasettings{'ACTION'}=$edit;}
|
||||
}
|
||||
#check if host with this ip already exists
|
||||
if (!&checkip(\%realserver,2))
|
||||
{
|
||||
$errormessage=$errormessage."<br>".$Lang::tr{'fwhost err ipcheck'};
|
||||
}
|
||||
return;
|
||||
}
|
||||
sub decrease
|
||||
{
|
||||
&General::readhasharray("$configvs", \%virtualserver);
|
||||
&General::readhasharray("$configrs", \%realserver);
|
||||
&General::writehasharray("$configvs", \%virtualserver);
|
||||
&General::writehasharray("$configrs", \%realserver);
|
||||
}
|
||||
sub validhostname
|
||||
{
|
||||
# Checks a hostname against RFC1035
|
||||
my $hostname = $_[0];
|
||||
|
||||
# Each part should be at least two characters in length
|
||||
# but no more than 63 characters
|
||||
if (length ($hostname) < 1 || length ($hostname) > 63) {
|
||||
return 0;}
|
||||
# Only valid characters are a-z, A-Z, 0-9 and -
|
||||
if ($hostname !~ /^[a-zA-ZäöüÖÄÜ0-9-_.;()\/\s]*$/) {
|
||||
return 0;}
|
||||
# First character can only be a letter or a digit
|
||||
if (substr ($hostname, 0, 1) !~ /^[a-zA-ZöäüÖÄÜ0-9]*$/) {
|
||||
return 0;}
|
||||
# Last character can only be a letter or a digit
|
||||
if (substr ($hostname, -1, 1) !~ /^[a-zA-ZöäüÖÄÜ0-9()]*$/) {
|
||||
return 0;}
|
||||
return 1;
|
||||
}
|
||||
sub validremark
|
||||
{
|
||||
# Checks a hostname against RFC1035
|
||||
my $remark = $_[0];
|
||||
# Each part should be at least two characters in length
|
||||
# but no more than 63 characters
|
||||
if (length ($remark) < 1 || length ($remark) > 255) {
|
||||
return 0;}
|
||||
# Only valid characters are a-z, A-Z, 0-9 and -
|
||||
if ($remark !~ /^[a-zäöüA-ZÖÄÜ0-9-.:;\|_()\/\s]*$/) {
|
||||
return 0;}
|
||||
# First character can only be a letter or a digit
|
||||
if (substr ($remark, 0, 1) !~ /^[a-zäöüA-ZÖÄÜ0-9]*$/) {
|
||||
return 0;}
|
||||
# Last character can only be a letter or a digit
|
||||
if (substr ($remark, -1, 1) !~ /^[a-zöäüA-ZÖÄÜ0-9.:;_)]*$/) {
|
||||
return 0;}
|
||||
return 1;
|
||||
}
|
||||
&Header::closebigbox();
|
||||
&Header::closepage();
|
||||
@@ -37,6 +37,7 @@ my %color = ();
|
||||
my %mainsettings = ();
|
||||
my %settings = ();
|
||||
my %cgiparams = ();
|
||||
my $errormessage='';
|
||||
|
||||
# Read configuration file.
|
||||
&General::readhash("$settingsfile", \%settings);
|
||||
@@ -63,30 +64,44 @@ if ($cgiparams{'ACTION'} eq $Lang::tr{'save'}) {
|
||||
# Loop through our locations array to prevent from
|
||||
# non existing countries or code.
|
||||
foreach my $cn (@locations) {
|
||||
# Check if blocking for this country should be enabled/disabled.
|
||||
if (exists $cgiparams{$cn}) {
|
||||
$settings{$cn} = "on";
|
||||
} else {
|
||||
$settings{$cn} = "off";
|
||||
# Get the current setting for the country (on/off)
|
||||
my $current_status = $settings{$cn};
|
||||
|
||||
# Determine if the country should be blocked based on CGI input
|
||||
my $new_status = exists $cgiparams{$cn} ? "on" : "off";
|
||||
|
||||
# Update settings based on the user input
|
||||
$settings{$cn} = $new_status;
|
||||
|
||||
# If the new status is "on" and the current status was "off", add the country's IPs
|
||||
if ($new_status eq "on" && $current_status eq "off") {
|
||||
# Call function to add IPs for this country to the eBPF map
|
||||
&add_country_ips($cn);
|
||||
} # If the new status is "off" and the current status was "on", remove the country's IPs
|
||||
elsif ($new_status eq "off" && $current_status eq "on") {
|
||||
# Call function to remove IPs for this country from the eBPF map
|
||||
&remove_country_ips($cn);
|
||||
}
|
||||
}
|
||||
|
||||
&General::writehash("$settingsfile", \%settings);
|
||||
|
||||
# Mark the firewall config as changed.
|
||||
&General::firewall_config_changed();
|
||||
|
||||
# Assign reload notice.
|
||||
$notice = $Lang::tr{'fw rules reload notice'};
|
||||
# Check if we want to disable locationblock.
|
||||
if ( $settings{'LOCATIONBLOCK_ENABLED'} eq "on" ) {
|
||||
&General::system('/usr/local/bin/xdpgeoipctrl', 'start');
|
||||
} else {
|
||||
&General::system('/usr/local/bin/xdpgeoipctrl', 'stop');
|
||||
}
|
||||
}
|
||||
|
||||
&Header::openpage($Lang::tr{'locationblock configuration'}, 1, '');
|
||||
|
||||
# Print notice that a firewall reload is required.
|
||||
if ($notice) {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'notice'});
|
||||
print "<font class='base'>$notice</font>";
|
||||
&Header::closebox();
|
||||
&Header::openbigbox('100%', 'left', '', $errormessage);
|
||||
|
||||
if ($errormessage) {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'error messages'});
|
||||
print "<font class='base' color=red>$errormessage </font>\n";
|
||||
&Header::closebox();
|
||||
}
|
||||
|
||||
# Checkbox pre-selection.
|
||||
@@ -269,3 +284,50 @@ print"</form>\n";
|
||||
|
||||
&Header::closebigbox();
|
||||
&Header::closepage();
|
||||
|
||||
sub add_country_ips {
|
||||
|
||||
my ($set) = @_;
|
||||
|
||||
# Libloc adds the IP type (v4 or v6) as part of the set and file name.
|
||||
my $loc_set = "$set" . "v4";
|
||||
|
||||
# The bare filename equals the set name.
|
||||
my $filename = $loc_set;
|
||||
|
||||
# Libloc uses "ipset" as file extension.
|
||||
my $file_extension = "ipset";
|
||||
|
||||
# Generate full path and filename for the ipset db file.
|
||||
my $db_file = "$Location::Functions::ipset_db_directory/$filename.$file_extension";
|
||||
|
||||
my @options;
|
||||
my $command = 'xdp_geoip';
|
||||
push(@options, "add", $db_file, $set);
|
||||
&General::system_output($command, @options);
|
||||
#my @output = &General::system_output($command, @options);
|
||||
#$errormessage = join('', @output);
|
||||
}
|
||||
|
||||
sub remove_country_ips {
|
||||
my ($set) = @_;
|
||||
|
||||
# Libloc adds the IP type (v4 or v6) as part of the set and file name.
|
||||
my $loc_set = "$set" . "v4";
|
||||
|
||||
# The bare filename equals the set name.
|
||||
my $filename = $loc_set;
|
||||
|
||||
# Libloc uses "ipset" as file extension.
|
||||
my $file_extension = "ipset";
|
||||
|
||||
# Generate full path and filename for the ipset db file.
|
||||
my $db_file = "$Location::Functions::ipset_db_directory/$filename.$file_extension";
|
||||
|
||||
my @options;
|
||||
my $command = 'xdp_geoip';
|
||||
push(@options, "delete", $db_file, $set);
|
||||
&General::system_output($command, @options);
|
||||
#my @output = &General::system_output($command, @save_options);
|
||||
#$errormessage = join('', @output);
|
||||
}
|
||||
|
||||
@@ -170,6 +170,10 @@ if ($reportsettings{'ACTION'} eq $Lang::tr{'calamaris create report'})
|
||||
|
||||
if ($reportsettings{'RUN_BACKGROUND'} eq 'on') { $commandline.=" &"; }
|
||||
|
||||
if (!($commandline =~ /^[a-zA-Z0-9-\s]+$/))
|
||||
{
|
||||
die "Invalid input in\"$commandline\"";
|
||||
}
|
||||
system("${General::swroot}/proxy/calamaris/bin/mkreport $commandline")
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,23 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# IPFire CGIs
|
||||
#
|
||||
# This code is distributed under the terms of the GPL
|
||||
#
|
||||
# (c) The IPFire Team
|
||||
#
|
||||
# $Id: config.dat,v 1.2.2.10 2005/06/14 12:32:07 eoberlander Exp $
|
||||
#
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2025 IPFire Team <info@ipfire.org> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
use strict;
|
||||
|
||||
@@ -143,6 +153,7 @@ END
|
||||
&Header::closebox();
|
||||
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'remote logging'});
|
||||
$logsettings{'REMOTELOG_ADDR'} = &Header::escape($logsettings{'REMOTELOG_ADDR'});
|
||||
print <<END
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
|
||||
@@ -1,14 +1,23 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# SmoothWall CGIs
|
||||
#
|
||||
# This code is distributed under the terms of the GPL
|
||||
#
|
||||
# JC HERITIER
|
||||
# page inspired from the initial firewalllog.dat
|
||||
#
|
||||
# Modified for IPFire by Christian Schmidt
|
||||
# and Michael Tremer (www.ipfire.org)
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2025 IPFire Team <info@ipfire.org> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
use strict;
|
||||
use Getopt::Std;
|
||||
@@ -270,7 +279,8 @@ print <<END
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan='3' align='left' valign="left">$Lang::tr{'Number of Countries for the pie chart'}:</td>
|
||||
<td colspan='3' align='left' valign="center"><input type='text' name='pienumber' value='$pienumber' size='4'></td>
|
||||
<td colspan='3' align='left' valign="center"><input type='text' name='pienumber'
|
||||
value='@{[ &Header::escape($pienumber) ]}' size='4'></td>
|
||||
<td align='right'><input type='submit' name='ACTION' value='$Lang::tr{'save'}' /></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -1,14 +1,23 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# SmoothWall CGIs
|
||||
#
|
||||
# This code is distributed under the terms of the GPL
|
||||
#
|
||||
# JC HERITIER
|
||||
# page inspired from the initial firewalllog.dat
|
||||
#
|
||||
# Modified for IPFire by Christian Schmidt
|
||||
# and Michael Tremer (www.ipfire.org)
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2025 IPFire Team <info@ipfire.org> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
use strict;
|
||||
use Getopt::Std;
|
||||
@@ -272,7 +281,8 @@ print <<END
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan='3' align='left' valign="left">$Lang::tr{'Number of IPs for the pie chart'}:</td>
|
||||
<td colspan='3' align='left' valign="center"><input type='text' name='pienumber' value='$pienumber' size='4'></td>
|
||||
<td colspan='3' align='left' valign="center"><input type='text' name='pienumber'
|
||||
value='@{[ &Header::escape($pienumber) ]}' size='4'></td>
|
||||
<td align='right'><input type='submit' name='ACTION' value='$Lang::tr{'save'}' /></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2020 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2020 - 2025 IPFire Team <info@ipfire.org> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
@@ -141,7 +141,7 @@ my $database_query = qq(
|
||||
ORDER BY common_name, duration DESC;
|
||||
);
|
||||
|
||||
if ($cgiparams{'CONNECTION_NAME'}) {
|
||||
if (($cgiparams{'CONNECTION_NAME'}) && ($cgiparams{'CONNECTION_NAME'} =~ /^[a-zA-Z0-9]+$/)) {
|
||||
$database_query = qq(
|
||||
SELECT common_name, DATETIME(connected_at, 'localtime'), DATETIME(disconnected_at, 'localtime'), bytes_received, bytes_sent,
|
||||
STRFTIME('%s', DATETIME(disconnected_at)) - STRFTIME('%s', DATETIME(connected_at)) AS duration FROM sessions
|
||||
|
||||
411
html/cgi-bin/logs.cgi/wireguardlog.dat
Normal file
411
html/cgi-bin/logs.cgi/wireguardlog.dat
Normal file
@@ -0,0 +1,411 @@
|
||||
#!/usr/bin/perl
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2023 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2025 LoongFire Team #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
use strict;
|
||||
|
||||
use Getopt::Std;
|
||||
|
||||
# enable only the following on debugging purpose
|
||||
#use warnings;
|
||||
#use CGI::Carp 'fatalsToBrowser';
|
||||
|
||||
require '/var/ipfire/general-functions.pl';
|
||||
require "${General::swroot}/location-functions.pl";
|
||||
require "${General::swroot}/lang.pl";
|
||||
require "${General::swroot}/header.pl";
|
||||
|
||||
my %color = ();
|
||||
my %mainsettings = ();
|
||||
&General::readhash("${General::swroot}/main/settings", \%mainsettings);
|
||||
&General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", \%color);
|
||||
|
||||
use POSIX();
|
||||
|
||||
#workaround to suppress a warning when a variable is used only once
|
||||
my @dummy = ( ${Header::table2colour} );
|
||||
undef (@dummy);
|
||||
|
||||
my %cgiparams=();
|
||||
my %logsettings=();
|
||||
my $errormessage = '';
|
||||
|
||||
my @shortmonths = ( 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug',
|
||||
'Sep', 'Oct', 'Nov', 'Dec' );
|
||||
my @longmonths = ( $Lang::tr{'january'}, $Lang::tr{'february'}, $Lang::tr{'march'},
|
||||
$Lang::tr{'april'}, $Lang::tr{'may'}, $Lang::tr{'june'}, $Lang::tr{'july'}, $Lang::tr{'august'},
|
||||
$Lang::tr{'september'}, $Lang::tr{'october'}, $Lang::tr{'november'},
|
||||
$Lang::tr{'december'} );
|
||||
|
||||
my @now = localtime();
|
||||
my $dow = $now[6];
|
||||
my $doy = $now[7];
|
||||
my $tdoy = $now[7];
|
||||
my $year = $now[5]+1900;
|
||||
|
||||
$cgiparams{'DAY'} = $now[3];
|
||||
$cgiparams{'MONTH'} = $now[4];
|
||||
$cgiparams{'ACTION'} = '';
|
||||
|
||||
&Header::getcgihash(\%cgiparams);
|
||||
$logsettings{'LOGVIEW_REVERSE'} = 'off';
|
||||
&General::readhash("${General::swroot}/logging/settings", \%logsettings);
|
||||
${Header::viewsize} = defined ($logsettings{'LOGVIEW_VIEWSIZE'}) ? $logsettings{'LOGVIEW_VIEWSIZE'} : 150;
|
||||
|
||||
my $start = ($logsettings{'LOGVIEW_REVERSE'} eq 'on') ? 0x7FFFF000 : 0; #index of firts line number to display
|
||||
|
||||
if ($ENV{'QUERY_STRING'} && $cgiparams{'ACTION'} ne $Lang::tr{'update'})
|
||||
{
|
||||
my @temp = split(',',$ENV{'QUERY_STRING'});
|
||||
$start = $temp[0];
|
||||
$cgiparams{'MONTH'} = $temp[1];
|
||||
$cgiparams{'DAY'} = $temp[2];
|
||||
}
|
||||
|
||||
if (!($cgiparams{'MONTH'} =~ /^(0|1|2|3|4|5|6|7|8|9|10|11)$/) ||
|
||||
!($cgiparams{'DAY'} =~ /^(0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31)$/))
|
||||
{
|
||||
$cgiparams{'DAY'} = $now[3];
|
||||
$cgiparams{'MONTH'} = $now[4];
|
||||
}
|
||||
elsif($cgiparams{'ACTION'} eq '>>')
|
||||
{
|
||||
my @temp_then=();
|
||||
my @temp_now = localtime(time);
|
||||
$temp_now[4] = $cgiparams{'MONTH'};
|
||||
$temp_now[3] = $cgiparams{'DAY'};
|
||||
if ($cgiparams{'DAY'}) {
|
||||
@temp_then = localtime(POSIX::mktime(@temp_now) + 86400);
|
||||
## Retrieve the same time on the next day +
|
||||
## 86400 seconds in a day
|
||||
} else {
|
||||
$temp_now[3] = 1;
|
||||
$temp_now[4] = ($temp_now[4]+1) %12;
|
||||
@temp_then = localtime(POSIX::mktime(@temp_now) );
|
||||
$temp_then[3] = 0;
|
||||
}
|
||||
$cgiparams{'MONTH'} = $temp_then[4];
|
||||
$cgiparams{'DAY'} = $temp_then[3];
|
||||
}
|
||||
elsif($cgiparams{'ACTION'} eq '<<')
|
||||
{
|
||||
my @temp_then=();
|
||||
my @temp_now = localtime(time);
|
||||
$temp_now[4] = $cgiparams{'MONTH'};
|
||||
$temp_now[3] = $cgiparams{'DAY'};
|
||||
if ($cgiparams{'DAY'}) {
|
||||
@temp_then = localtime(POSIX::mktime(@temp_now) - 86400);
|
||||
## Retrieve the same time on the next day -
|
||||
## 86400 seconds in a day
|
||||
} else {
|
||||
$temp_now[3] = 1;
|
||||
$temp_now[4] = ($temp_now[4]-1) %12;
|
||||
@temp_then = localtime(POSIX::mktime(@temp_now) );
|
||||
$temp_then[3] = 0;
|
||||
}
|
||||
$cgiparams{'MONTH'} = $temp_then[4];
|
||||
$cgiparams{'DAY'} = $temp_then[3];
|
||||
}
|
||||
|
||||
# Find in which file.gz is the log. Can be calculated because WEEKLY ROTATING of access.log
|
||||
my $gzindex;
|
||||
my $date = $cgiparams{'DAY'} == 0 ? '' : $cgiparams{'DAY'} <= 9 ? "0$cgiparams{'DAY'}" : "$cgiparams{'DAY'}";
|
||||
|
||||
{
|
||||
my $xday;
|
||||
|
||||
# Calculate time. If future date, calculate for past year !!!
|
||||
if (( $cgiparams{'MONTH'} eq $now[4]) && ($cgiparams{'DAY'} > $now[3]) ||
|
||||
( $cgiparams{'MONTH'} > $now[4] ) ) {
|
||||
$xday = POSIX::mktime( 0, 0, 0, $cgiparams{'DAY'}, $cgiparams{'MONTH'}, $year - 1901 );
|
||||
$date = "$longmonths[$cgiparams{'MONTH'}] $date, ". int($year-1);
|
||||
} else {
|
||||
$xday = POSIX::mktime( 0, 0, 0, $cgiparams{'DAY'}, $cgiparams{'MONTH'}, $year - 1900 );
|
||||
$date = "$longmonths[$cgiparams{'MONTH'}] $date, $year";
|
||||
}
|
||||
|
||||
# calculate end of active week (saturday 23H59)
|
||||
my @then = ();
|
||||
@then = localtime(time());
|
||||
my $sunday = POSIX::mktime( 0, 0, 0, @then[3], @then[4], @then[5]);
|
||||
$sunday += (6-$then[6]) * 86400;
|
||||
|
||||
# Convert delta in second to full weeks
|
||||
$gzindex = int (($sunday-$xday)/604800 );
|
||||
}
|
||||
|
||||
my $monthstr = $shortmonths[$cgiparams{'MONTH'}];
|
||||
my $daystr = $cgiparams{'DAY'} == 0 ? '..' : $cgiparams{'DAY'} <= 9 ? " $cgiparams{'DAY'}" : "$cgiparams{'DAY'}";
|
||||
|
||||
my $lines = 0;
|
||||
my @log=();
|
||||
|
||||
my $loop = 1;
|
||||
my $filestr = 0;
|
||||
my $lastdatetime; # for debug
|
||||
my $search_for_end = 0;
|
||||
|
||||
while ($gzindex >=0 && $loop) {
|
||||
# calculate file name
|
||||
if ($gzindex == 0) {
|
||||
$filestr = "/var/log/messages";
|
||||
} else {
|
||||
$filestr = "/var/log/messages.$gzindex";
|
||||
$filestr = "$filestr.gz" if -f "$filestr.gz";
|
||||
}
|
||||
# now read file if existing
|
||||
if (open (FILE,($filestr =~ /.gz$/ ? "gzip -dc $filestr |" : $filestr))) {
|
||||
#&General::log("reading $filestr");
|
||||
READ:while (<FILE>) {
|
||||
my $line = $_;
|
||||
if ($line =~ /^${monthstr} ${daystr} ..:..:.. [\w\-]+ wireguard-handshake\[\d+\]:.*$/) {
|
||||
# when standart viewing, just keep in memory the correct slice
|
||||
# it starts a '$start' and size is $viewport
|
||||
# If export, then keep all lines...
|
||||
if ($cgiparams{'ACTION'} eq $Lang::tr{'export'}){
|
||||
$log[$lines++] = "$line";
|
||||
} else {
|
||||
if ($lines++ < ($start + $Header::viewsize)) {
|
||||
push(@log,"$line");
|
||||
if (@log > $Header::viewsize) {
|
||||
shift (@log);
|
||||
}
|
||||
#} else { dont do this optimisation, need to count lines !
|
||||
# $datetime = $maxtime; # we have read viewsize lines, stop main loop
|
||||
# last READ; # exit read file
|
||||
}
|
||||
}
|
||||
$search_for_end = 1; # we find the start of slice, can look for end now
|
||||
} else {
|
||||
if ($search_for_end == 1) {
|
||||
#finish read files when date is over (test month equality only)
|
||||
$line =~ /^(...) (..) ..:..:..*$/;
|
||||
$loop = 0 if ( ($1 ne $monthstr) || ( ($daystr ne '..') && ($daystr ne $2) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
close (FILE);
|
||||
}
|
||||
$gzindex--; # will try next gz file eg 40,39,38,.... because it may have holes when ipcop stopped
|
||||
# for a long time
|
||||
}# while
|
||||
|
||||
# $errormessage = "$Lang::tr{'date not in logs'}: $filestr $Lang::tr{'could not be opened'}";
|
||||
|
||||
if ($cgiparams{'ACTION'} eq $Lang::tr{'export'})
|
||||
{
|
||||
print "Content-type: text/plain\n\n";
|
||||
print "Wireguard handshake log\r\n";
|
||||
print "$Lang::{'date'}: $date\r\n\r\n";
|
||||
|
||||
if ($logsettings{'LOGVIEW_REVERSE'} eq 'on') { @log = reverse @log; }
|
||||
|
||||
foreach $_ (@log)
|
||||
{
|
||||
/^... (..) (..:..:..) [\w\-]+ wireguard-handshake\[\d+\]: .*?\((\d+\.\d+\.\d+\.\d+:\d+)\)$/;
|
||||
my $day = $1;
|
||||
$day =~ tr / /0/;
|
||||
my $time = $cgiparams{'DAY'} ? "$2" : "$day/$2" ;
|
||||
my $peer = $3;
|
||||
print "$time $peer\r\n";
|
||||
|
||||
}
|
||||
exit 0;
|
||||
}
|
||||
|
||||
&Header::showhttpheaders();
|
||||
|
||||
&Header::openpage($Lang::tr{'wg log'}, 1, '');
|
||||
|
||||
&Header::openbigbox('100%', 'left', '', $errormessage);
|
||||
|
||||
if ($errormessage) {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'error messages'});
|
||||
print "<font class='base'>$errormessage </font>\n";
|
||||
&Header::closebox();
|
||||
}
|
||||
|
||||
&Header::openbox('100%', 'left', "$Lang::tr{'settings'}");
|
||||
|
||||
print <<END
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td width='10%' class='base'>$Lang::tr{'month'}: </td>
|
||||
<td width='10%'>
|
||||
<select name='MONTH'>
|
||||
END
|
||||
;
|
||||
for (my $month = 0; $month < 12; $month++)
|
||||
{
|
||||
print "\t<option ";
|
||||
if ($month == $cgiparams{'MONTH'}) {
|
||||
print "selected='selected' ";
|
||||
}
|
||||
print "value='$month'>$longmonths[$month]</option>\n";
|
||||
}
|
||||
print <<END
|
||||
</select>
|
||||
</td>
|
||||
<td width='10%' class='base' align='right'> $Lang::tr{'day'}: </td>
|
||||
<td width='40%'>
|
||||
<select name='DAY'>
|
||||
END
|
||||
;
|
||||
print "<option value='0'>$Lang::tr{'all'}</option>\n";
|
||||
for (my $day = 1; $day <= 31; $day++)
|
||||
{
|
||||
print "\t<option ";
|
||||
if ($day == $cgiparams{'DAY'}) {
|
||||
print "selected='selected' ";
|
||||
}
|
||||
print "value='$day'>$day</option>\n";
|
||||
}
|
||||
print <<END
|
||||
</select>
|
||||
</td>
|
||||
<td width='5%' align='center'><input type='submit' name='ACTION' title='$Lang::tr{'day before'}' value='<<' /></td>
|
||||
<td width='5%' align='center'><input type='submit' name='ACTION' title='$Lang::tr{'day after'}' value='>>' /></td>
|
||||
<td width='10%' align='center'><input type='submit' name='ACTION' value='$Lang::tr{'update'}' /></td>
|
||||
<td width='10%' align='center'><input type='submit' name='ACTION' value='$Lang::tr{'export'}' /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
END
|
||||
;
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'log'});
|
||||
print "<p><b>$Lang::tr{'wg hits'} $date: $lines</b></p>";
|
||||
|
||||
my $lastPageIndex = $lines - ${Header::viewsize};
|
||||
$start = $lastPageIndex if ($start >= $lastPageIndex);
|
||||
$start = 0 if ($start < 0);
|
||||
|
||||
my $prev;
|
||||
if ($start == 0) {
|
||||
$prev = -1;
|
||||
} else {
|
||||
$prev = $start - ${Header::viewsize};
|
||||
$prev = 0 if ( $prev < 0);
|
||||
}
|
||||
|
||||
my $next;
|
||||
if ($start == $lastPageIndex) {
|
||||
$next = -1;
|
||||
} else {
|
||||
$next = $start + ${Header::viewsize};
|
||||
$next = $lines - ${Header::viewsize} if ($next >= $lines - ${Header::viewsize});
|
||||
}
|
||||
|
||||
if ($logsettings{'LOGVIEW_REVERSE'} eq 'on') { @log = reverse @log; }
|
||||
if ($lines != 0) { &oldernewer(); }
|
||||
|
||||
print <<END
|
||||
<table width='100%' class='tbl'>
|
||||
<tr>
|
||||
<th align='center' class='boldbase'><b>$Lang::tr{'time'}</b></th>
|
||||
<th align='center' class='boldbase'><b>$Lang::tr{'wg peer'}</b></th>
|
||||
</tr>
|
||||
END
|
||||
;
|
||||
|
||||
|
||||
$lines = 0;
|
||||
foreach $_ (@log)
|
||||
{
|
||||
my ($day, $time, $srcaddr);
|
||||
if ($_ =~ /^... (..) (..:..:..) [\w\-]+ wireguard-handshake\[\d+\]: .*?\((\d+\.\d+\.\d+\.\d+:\d+)\)$/) {
|
||||
$day = $1;
|
||||
$day =~ tr / /0/;
|
||||
$time = $cgiparams{'DAY'} ? "$2" : "$day/$2" ;
|
||||
$srcaddr = $3;
|
||||
|
||||
}
|
||||
|
||||
my $col="";
|
||||
if ($lines % 2) {
|
||||
print "<tr>";
|
||||
$col="bgcolor='$color{'color20'}'";
|
||||
}
|
||||
else {
|
||||
print "<tr>";
|
||||
$col="bgcolor='$color{'color22'}'";
|
||||
}
|
||||
print <<END
|
||||
|
||||
<td align='center' $col>$time</td>
|
||||
<td align='center' $col>$srcaddr</td>
|
||||
END
|
||||
;
|
||||
print <<END
|
||||
</tr>
|
||||
END
|
||||
;
|
||||
$lines++;
|
||||
}
|
||||
|
||||
print "</table>";
|
||||
|
||||
&oldernewer();
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::closebigbox();
|
||||
|
||||
&Header::closepage();
|
||||
|
||||
sub oldernewer
|
||||
{
|
||||
print <<END
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
END
|
||||
;
|
||||
|
||||
print "<td align='center' width='50%'>";
|
||||
if ($prev != -1) {
|
||||
print "<a href='/cgi-bin/logs.cgi/wireguardlog.dat?0,$cgiparams{'MONTH'},$cgiparams{'DAY'}'>$Lang::tr{'first'}</a> ";
|
||||
print "<a href='/cgi-bin/logs.cgi/wireguardlog.dat?$prev,$cgiparams{'MONTH'},$cgiparams{'DAY'}'>$Lang::tr{'older'}</a>";
|
||||
}
|
||||
else {
|
||||
print "$Lang::tr{'first'} $Lang::tr{'older'}";
|
||||
}
|
||||
print "</td>\n";
|
||||
|
||||
print "<td align='center' width='50%'>";
|
||||
if ($next >= 0) {
|
||||
print "<a href='/cgi-bin/logs.cgi/wireguardlog.dat?$next,$cgiparams{'MONTH'},$cgiparams{'DAY'}'>$Lang::tr{'newer'}</a> ";
|
||||
print "<a href='/cgi-bin/logs.cgi/wireguardlog.dat?$lastPageIndex,$cgiparams{'MONTH'},$cgiparams{'DAY'}'>$Lang::tr{'last'}</a>";
|
||||
}
|
||||
else {
|
||||
print "$Lang::tr{'newer'} $Lang::tr{'last'} ";
|
||||
}
|
||||
print "</td>\n";
|
||||
|
||||
print <<END
|
||||
</tr>
|
||||
</table>
|
||||
END
|
||||
;
|
||||
}
|
||||
|
||||
414
html/cgi-bin/logs.cgi/xdpdnslog.dat
Normal file
414
html/cgi-bin/logs.cgi/xdpdnslog.dat
Normal file
@@ -0,0 +1,414 @@
|
||||
#!/usr/bin/perl
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2023 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2024 BPFire Team #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
use strict;
|
||||
|
||||
use Getopt::Std;
|
||||
|
||||
# enable only the following on debugging purpose
|
||||
#use warnings;
|
||||
#use CGI::Carp 'fatalsToBrowser';
|
||||
|
||||
require '/var/ipfire/general-functions.pl';
|
||||
require "${General::swroot}/location-functions.pl";
|
||||
require "${General::swroot}/lang.pl";
|
||||
require "${General::swroot}/header.pl";
|
||||
|
||||
my %color = ();
|
||||
my %mainsettings = ();
|
||||
&General::readhash("${General::swroot}/main/settings", \%mainsettings);
|
||||
&General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", \%color);
|
||||
|
||||
use POSIX();
|
||||
|
||||
#workaround to suppress a warning when a variable is used only once
|
||||
my @dummy = ( ${Header::table2colour} );
|
||||
undef (@dummy);
|
||||
|
||||
my %cgiparams=();
|
||||
my %logsettings=();
|
||||
my $errormessage = '';
|
||||
|
||||
my @shortmonths = ( 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug',
|
||||
'Sep', 'Oct', 'Nov', 'Dec' );
|
||||
my @longmonths = ( $Lang::tr{'january'}, $Lang::tr{'february'}, $Lang::tr{'march'},
|
||||
$Lang::tr{'april'}, $Lang::tr{'may'}, $Lang::tr{'june'}, $Lang::tr{'july'}, $Lang::tr{'august'},
|
||||
$Lang::tr{'september'}, $Lang::tr{'october'}, $Lang::tr{'november'},
|
||||
$Lang::tr{'december'} );
|
||||
|
||||
my @now = localtime();
|
||||
my $dow = $now[6];
|
||||
my $doy = $now[7];
|
||||
my $tdoy = $now[7];
|
||||
my $year = $now[5]+1900;
|
||||
|
||||
$cgiparams{'DAY'} = $now[3];
|
||||
$cgiparams{'MONTH'} = $now[4];
|
||||
$cgiparams{'ACTION'} = '';
|
||||
|
||||
&Header::getcgihash(\%cgiparams);
|
||||
$logsettings{'LOGVIEW_REVERSE'} = 'off';
|
||||
&General::readhash("${General::swroot}/logging/settings", \%logsettings);
|
||||
${Header::viewsize} = defined ($logsettings{'LOGVIEW_VIEWSIZE'}) ? $logsettings{'LOGVIEW_VIEWSIZE'} : 150;
|
||||
|
||||
my $start = ($logsettings{'LOGVIEW_REVERSE'} eq 'on') ? 0x7FFFF000 : 0; #index of firts line number to display
|
||||
|
||||
if ($ENV{'QUERY_STRING'} && $cgiparams{'ACTION'} ne $Lang::tr{'update'})
|
||||
{
|
||||
my @temp = split(',',$ENV{'QUERY_STRING'});
|
||||
$start = $temp[0];
|
||||
$cgiparams{'MONTH'} = $temp[1];
|
||||
$cgiparams{'DAY'} = $temp[2];
|
||||
}
|
||||
|
||||
if (!($cgiparams{'MONTH'} =~ /^(0|1|2|3|4|5|6|7|8|9|10|11)$/) ||
|
||||
!($cgiparams{'DAY'} =~ /^(0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31)$/))
|
||||
{
|
||||
$cgiparams{'DAY'} = $now[3];
|
||||
$cgiparams{'MONTH'} = $now[4];
|
||||
}
|
||||
elsif($cgiparams{'ACTION'} eq '>>')
|
||||
{
|
||||
my @temp_then=();
|
||||
my @temp_now = localtime(time);
|
||||
$temp_now[4] = $cgiparams{'MONTH'};
|
||||
$temp_now[3] = $cgiparams{'DAY'};
|
||||
if ($cgiparams{'DAY'}) {
|
||||
@temp_then = localtime(POSIX::mktime(@temp_now) + 86400);
|
||||
## Retrieve the same time on the next day +
|
||||
## 86400 seconds in a day
|
||||
} else {
|
||||
$temp_now[3] = 1;
|
||||
$temp_now[4] = ($temp_now[4]+1) %12;
|
||||
@temp_then = localtime(POSIX::mktime(@temp_now) );
|
||||
$temp_then[3] = 0;
|
||||
}
|
||||
$cgiparams{'MONTH'} = $temp_then[4];
|
||||
$cgiparams{'DAY'} = $temp_then[3];
|
||||
}
|
||||
elsif($cgiparams{'ACTION'} eq '<<')
|
||||
{
|
||||
my @temp_then=();
|
||||
my @temp_now = localtime(time);
|
||||
$temp_now[4] = $cgiparams{'MONTH'};
|
||||
$temp_now[3] = $cgiparams{'DAY'};
|
||||
if ($cgiparams{'DAY'}) {
|
||||
@temp_then = localtime(POSIX::mktime(@temp_now) - 86400);
|
||||
## Retrieve the same time on the next day -
|
||||
## 86400 seconds in a day
|
||||
} else {
|
||||
$temp_now[3] = 1;
|
||||
$temp_now[4] = ($temp_now[4]-1) %12;
|
||||
@temp_then = localtime(POSIX::mktime(@temp_now) );
|
||||
$temp_then[3] = 0;
|
||||
}
|
||||
$cgiparams{'MONTH'} = $temp_then[4];
|
||||
$cgiparams{'DAY'} = $temp_then[3];
|
||||
}
|
||||
|
||||
# Find in which file.gz is the log. Can be calculated because WEEKLY ROTATING of access.log
|
||||
my $gzindex;
|
||||
my $date = $cgiparams{'DAY'} == 0 ? '' : $cgiparams{'DAY'} <= 9 ? "0$cgiparams{'DAY'}" : "$cgiparams{'DAY'}";
|
||||
|
||||
{
|
||||
my $xday;
|
||||
|
||||
# Calculate time. If future date, calculate for past year !!!
|
||||
if (( $cgiparams{'MONTH'} eq $now[4]) && ($cgiparams{'DAY'} > $now[3]) ||
|
||||
( $cgiparams{'MONTH'} > $now[4] ) ) {
|
||||
$xday = POSIX::mktime( 0, 0, 0, $cgiparams{'DAY'}, $cgiparams{'MONTH'}, $year - 1901 );
|
||||
$date = "$longmonths[$cgiparams{'MONTH'}] $date, ". int($year-1);
|
||||
} else {
|
||||
$xday = POSIX::mktime( 0, 0, 0, $cgiparams{'DAY'}, $cgiparams{'MONTH'}, $year - 1900 );
|
||||
$date = "$longmonths[$cgiparams{'MONTH'}] $date, $year";
|
||||
}
|
||||
|
||||
# calculate end of active week (saturday 23H59)
|
||||
my @then = ();
|
||||
@then = localtime(time());
|
||||
my $sunday = POSIX::mktime( 0, 0, 0, @then[3], @then[4], @then[5]);
|
||||
$sunday += (6-$then[6]) * 86400;
|
||||
|
||||
# Convert delta in second to full weeks
|
||||
$gzindex = int (($sunday-$xday)/604800 );
|
||||
}
|
||||
|
||||
my $monthstr = $shortmonths[$cgiparams{'MONTH'}];
|
||||
my $daystr = $cgiparams{'DAY'} == 0 ? '..' : $cgiparams{'DAY'} <= 9 ? " $cgiparams{'DAY'}" : "$cgiparams{'DAY'}";
|
||||
|
||||
my $lines = 0;
|
||||
my @log=();
|
||||
|
||||
my $loop = 1;
|
||||
my $filestr = 0;
|
||||
my $lastdatetime; # for debug
|
||||
my $search_for_end = 0;
|
||||
|
||||
while ($gzindex >=0 && $loop) {
|
||||
# calculate file name
|
||||
if ($gzindex == 0) {
|
||||
$filestr = "/var/log/messages";
|
||||
} else {
|
||||
$filestr = "/var/log/messages.$gzindex";
|
||||
$filestr = "$filestr.gz" if -f "$filestr.gz";
|
||||
}
|
||||
# now read file if existing
|
||||
if (open (FILE,($filestr =~ /.gz$/ ? "gzip -dc $filestr |" : $filestr))) {
|
||||
#&General::log("reading $filestr");
|
||||
READ:while (<FILE>) {
|
||||
my $line = $_;
|
||||
if ($line =~ /^${monthstr} ${daystr} ..:..:.. [\w\-]+ qname_logger\[\d+\]:.*$/) {
|
||||
# when standart viewing, just keep in memory the correct slice
|
||||
# it starts a '$start' and size is $viewport
|
||||
# If export, then keep all lines...
|
||||
if ($cgiparams{'ACTION'} eq $Lang::tr{'export'}){
|
||||
$log[$lines++] = "$line";
|
||||
} else {
|
||||
if ($lines++ < ($start + $Header::viewsize)) {
|
||||
push(@log,"$line");
|
||||
if (@log > $Header::viewsize) {
|
||||
shift (@log);
|
||||
}
|
||||
#} else { dont do this optimisation, need to count lines !
|
||||
# $datetime = $maxtime; # we have read viewsize lines, stop main loop
|
||||
# last READ; # exit read file
|
||||
}
|
||||
}
|
||||
$search_for_end = 1; # we find the start of slice, can look for end now
|
||||
} else {
|
||||
if ($search_for_end == 1) {
|
||||
#finish read files when date is over (test month equality only)
|
||||
$line =~ /^(...) (..) ..:..:..*$/;
|
||||
$loop = 0 if ( ($1 ne $monthstr) || ( ($daystr ne '..') && ($daystr ne $2) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
close (FILE);
|
||||
}
|
||||
$gzindex--; # will try next gz file eg 40,39,38,.... because it may have holes when ipcop stopped
|
||||
# for a long time
|
||||
}# while
|
||||
|
||||
# $errormessage = "$Lang::tr{'date not in logs'}: $filestr $Lang::tr{'could not be opened'}";
|
||||
|
||||
if ($cgiparams{'ACTION'} eq $Lang::tr{'export'})
|
||||
{
|
||||
print "Content-type: text/plain\n\n";
|
||||
print "BPFire XDP DNS log\r\n";
|
||||
print "$Lang::{'date'}: $date\r\n\r\n";
|
||||
|
||||
if ($logsettings{'LOGVIEW_REVERSE'} eq 'on') { @log = reverse @log; }
|
||||
|
||||
foreach $_ (@log)
|
||||
{
|
||||
/^... (..) (..:..:..) [\w\-]+ qname_logger\[\d+\]: Received qname: (.*) from source IP: (.*)$/;
|
||||
my $day = $1;
|
||||
$day =~ tr / /0/;
|
||||
my $time = $cgiparams{'DAY'} ? "$2" : "$day/$2" ;
|
||||
my $domain = $3;
|
||||
print "$time $domain $4\r\n";
|
||||
|
||||
}
|
||||
exit 0;
|
||||
}
|
||||
|
||||
&Header::showhttpheaders();
|
||||
|
||||
&Header::openpage($Lang::tr{'xdpdns log'}, 1, '');
|
||||
|
||||
&Header::openbigbox('100%', 'left', '', $errormessage);
|
||||
|
||||
if ($errormessage) {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'error messages'});
|
||||
print "<font class='base'>$errormessage </font>\n";
|
||||
&Header::closebox();
|
||||
}
|
||||
|
||||
&Header::openbox('100%', 'left', "$Lang::tr{'settings'}");
|
||||
|
||||
print <<END
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td width='10%' class='base'>$Lang::tr{'month'}: </td>
|
||||
<td width='10%'>
|
||||
<select name='MONTH'>
|
||||
END
|
||||
;
|
||||
for (my $month = 0; $month < 12; $month++)
|
||||
{
|
||||
print "\t<option ";
|
||||
if ($month == $cgiparams{'MONTH'}) {
|
||||
print "selected='selected' ";
|
||||
}
|
||||
print "value='$month'>$longmonths[$month]</option>\n";
|
||||
}
|
||||
print <<END
|
||||
</select>
|
||||
</td>
|
||||
<td width='10%' class='base' align='right'> $Lang::tr{'day'}: </td>
|
||||
<td width='40%'>
|
||||
<select name='DAY'>
|
||||
END
|
||||
;
|
||||
print "<option value='0'>$Lang::tr{'all'}</option>\n";
|
||||
for (my $day = 1; $day <= 31; $day++)
|
||||
{
|
||||
print "\t<option ";
|
||||
if ($day == $cgiparams{'DAY'}) {
|
||||
print "selected='selected' ";
|
||||
}
|
||||
print "value='$day'>$day</option>\n";
|
||||
}
|
||||
print <<END
|
||||
</select>
|
||||
</td>
|
||||
<td width='5%' align='center'><input type='submit' name='ACTION' title='$Lang::tr{'day before'}' value='<<' /></td>
|
||||
<td width='5%' align='center'><input type='submit' name='ACTION' title='$Lang::tr{'day after'}' value='>>' /></td>
|
||||
<td width='10%' align='center'><input type='submit' name='ACTION' value='$Lang::tr{'update'}' /></td>
|
||||
<td width='10%' align='center'><input type='submit' name='ACTION' value='$Lang::tr{'export'}' /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
END
|
||||
;
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'log'});
|
||||
print "<p><b>$Lang::tr{'xdpdns hits'} $date: $lines</b></p>";
|
||||
|
||||
my $lastPageIndex = $lines - ${Header::viewsize};
|
||||
$start = $lastPageIndex if ($start >= $lastPageIndex);
|
||||
$start = 0 if ($start < 0);
|
||||
|
||||
my $prev;
|
||||
if ($start == 0) {
|
||||
$prev = -1;
|
||||
} else {
|
||||
$prev = $start - ${Header::viewsize};
|
||||
$prev = 0 if ( $prev < 0);
|
||||
}
|
||||
|
||||
my $next;
|
||||
if ($start == $lastPageIndex) {
|
||||
$next = -1;
|
||||
} else {
|
||||
$next = $start + ${Header::viewsize};
|
||||
$next = $lines - ${Header::viewsize} if ($next >= $lines - ${Header::viewsize});
|
||||
}
|
||||
|
||||
if ($logsettings{'LOGVIEW_REVERSE'} eq 'on') { @log = reverse @log; }
|
||||
if ($lines != 0) { &oldernewer(); }
|
||||
|
||||
print <<END
|
||||
<table width='100%' class='tbl'>
|
||||
<tr>
|
||||
<th align='center' class='boldbase'><b>$Lang::tr{'time'}</b></th>
|
||||
<th align='center' class='boldbase'><b>$Lang::tr{'domain name'}</b></th>
|
||||
<th align='center' class='boldbase'><b>$Lang::tr{'source'}</b></th>
|
||||
</tr>
|
||||
END
|
||||
;
|
||||
|
||||
|
||||
$lines = 0;
|
||||
foreach $_ (@log)
|
||||
{
|
||||
my ($day, $time, $domain, $srcaddr);
|
||||
if ($_ =~ /^... (..) (..:..:..) [\w\-]+ qname_logger\[\d+\]: Received qname: (.*) from source IP: (.*)$/) {
|
||||
$day = $1;
|
||||
$day =~ tr / /0/;
|
||||
$time = $cgiparams{'DAY'} ? "$2" : "$day/$2" ;
|
||||
$domain = $3;
|
||||
$srcaddr = $4;
|
||||
|
||||
}
|
||||
|
||||
my $col="";
|
||||
if ($lines % 2) {
|
||||
print "<tr>";
|
||||
$col="bgcolor='$color{'color20'}'";
|
||||
}
|
||||
else {
|
||||
print "<tr>";
|
||||
$col="bgcolor='$color{'color22'}'";
|
||||
}
|
||||
print <<END
|
||||
|
||||
<td align='center' $col>$time</td>
|
||||
<td align='center' $col>$domain</td>
|
||||
<td align='center' $col>$srcaddr</td>
|
||||
END
|
||||
;
|
||||
print <<END
|
||||
</tr>
|
||||
END
|
||||
;
|
||||
$lines++;
|
||||
}
|
||||
|
||||
print "</table>";
|
||||
|
||||
&oldernewer();
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::closebigbox();
|
||||
|
||||
&Header::closepage();
|
||||
|
||||
sub oldernewer
|
||||
{
|
||||
print <<END
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
END
|
||||
;
|
||||
|
||||
print "<td align='center' width='50%'>";
|
||||
if ($prev != -1) {
|
||||
print "<a href='/cgi-bin/logs.cgi/xdpdnslog.dat?0,$cgiparams{'MONTH'},$cgiparams{'DAY'}'>$Lang::tr{'first'}</a> ";
|
||||
print "<a href='/cgi-bin/logs.cgi/xdpdnslog.dat?$prev,$cgiparams{'MONTH'},$cgiparams{'DAY'}'>$Lang::tr{'older'}</a>";
|
||||
}
|
||||
else {
|
||||
print "$Lang::tr{'first'} $Lang::tr{'older'}";
|
||||
}
|
||||
print "</td>\n";
|
||||
|
||||
print "<td align='center' width='50%'>";
|
||||
if ($next >= 0) {
|
||||
print "<a href='/cgi-bin/logs.cgi/xdpdnslog.dat?$next,$cgiparams{'MONTH'},$cgiparams{'DAY'}'>$Lang::tr{'newer'}</a> ";
|
||||
print "<a href='/cgi-bin/logs.cgi/xdpdnslog.dat?$lastPageIndex,$cgiparams{'MONTH'},$cgiparams{'DAY'}'>$Lang::tr{'last'}</a>";
|
||||
}
|
||||
else {
|
||||
print "$Lang::tr{'newer'} $Lang::tr{'last'} ";
|
||||
}
|
||||
print "</td>\n";
|
||||
|
||||
print <<END
|
||||
</tr>
|
||||
</table>
|
||||
END
|
||||
;
|
||||
}
|
||||
|
||||
414
html/cgi-bin/logs.cgi/xdpsnilog.dat
Normal file
414
html/cgi-bin/logs.cgi/xdpsnilog.dat
Normal file
@@ -0,0 +1,414 @@
|
||||
#!/usr/bin/perl
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2023 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2024 BPFire Team #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
use strict;
|
||||
|
||||
use Getopt::Std;
|
||||
|
||||
# enable only the following on debugging purpose
|
||||
#use warnings;
|
||||
#use CGI::Carp 'fatalsToBrowser';
|
||||
|
||||
require '/var/ipfire/general-functions.pl';
|
||||
require "${General::swroot}/location-functions.pl";
|
||||
require "${General::swroot}/lang.pl";
|
||||
require "${General::swroot}/header.pl";
|
||||
|
||||
my %color = ();
|
||||
my %mainsettings = ();
|
||||
&General::readhash("${General::swroot}/main/settings", \%mainsettings);
|
||||
&General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", \%color);
|
||||
|
||||
use POSIX();
|
||||
|
||||
#workaround to suppress a warning when a variable is used only once
|
||||
my @dummy = ( ${Header::table2colour} );
|
||||
undef (@dummy);
|
||||
|
||||
my %cgiparams=();
|
||||
my %logsettings=();
|
||||
my $errormessage = '';
|
||||
|
||||
my @shortmonths = ( 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug',
|
||||
'Sep', 'Oct', 'Nov', 'Dec' );
|
||||
my @longmonths = ( $Lang::tr{'january'}, $Lang::tr{'february'}, $Lang::tr{'march'},
|
||||
$Lang::tr{'april'}, $Lang::tr{'may'}, $Lang::tr{'june'}, $Lang::tr{'july'}, $Lang::tr{'august'},
|
||||
$Lang::tr{'september'}, $Lang::tr{'october'}, $Lang::tr{'november'},
|
||||
$Lang::tr{'december'} );
|
||||
|
||||
my @now = localtime();
|
||||
my $dow = $now[6];
|
||||
my $doy = $now[7];
|
||||
my $tdoy = $now[7];
|
||||
my $year = $now[5]+1900;
|
||||
|
||||
$cgiparams{'DAY'} = $now[3];
|
||||
$cgiparams{'MONTH'} = $now[4];
|
||||
$cgiparams{'ACTION'} = '';
|
||||
|
||||
&Header::getcgihash(\%cgiparams);
|
||||
$logsettings{'LOGVIEW_REVERSE'} = 'off';
|
||||
&General::readhash("${General::swroot}/logging/settings", \%logsettings);
|
||||
${Header::viewsize} = defined ($logsettings{'LOGVIEW_VIEWSIZE'}) ? $logsettings{'LOGVIEW_VIEWSIZE'} : 150;
|
||||
|
||||
my $start = ($logsettings{'LOGVIEW_REVERSE'} eq 'on') ? 0x7FFFF000 : 0; #index of firts line number to display
|
||||
|
||||
if ($ENV{'QUERY_STRING'} && $cgiparams{'ACTION'} ne $Lang::tr{'update'})
|
||||
{
|
||||
my @temp = split(',',$ENV{'QUERY_STRING'});
|
||||
$start = $temp[0];
|
||||
$cgiparams{'MONTH'} = $temp[1];
|
||||
$cgiparams{'DAY'} = $temp[2];
|
||||
}
|
||||
|
||||
if (!($cgiparams{'MONTH'} =~ /^(0|1|2|3|4|5|6|7|8|9|10|11)$/) ||
|
||||
!($cgiparams{'DAY'} =~ /^(0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31)$/))
|
||||
{
|
||||
$cgiparams{'DAY'} = $now[3];
|
||||
$cgiparams{'MONTH'} = $now[4];
|
||||
}
|
||||
elsif($cgiparams{'ACTION'} eq '>>')
|
||||
{
|
||||
my @temp_then=();
|
||||
my @temp_now = localtime(time);
|
||||
$temp_now[4] = $cgiparams{'MONTH'};
|
||||
$temp_now[3] = $cgiparams{'DAY'};
|
||||
if ($cgiparams{'DAY'}) {
|
||||
@temp_then = localtime(POSIX::mktime(@temp_now) + 86400);
|
||||
## Retrieve the same time on the next day +
|
||||
## 86400 seconds in a day
|
||||
} else {
|
||||
$temp_now[3] = 1;
|
||||
$temp_now[4] = ($temp_now[4]+1) %12;
|
||||
@temp_then = localtime(POSIX::mktime(@temp_now) );
|
||||
$temp_then[3] = 0;
|
||||
}
|
||||
$cgiparams{'MONTH'} = $temp_then[4];
|
||||
$cgiparams{'DAY'} = $temp_then[3];
|
||||
}
|
||||
elsif($cgiparams{'ACTION'} eq '<<')
|
||||
{
|
||||
my @temp_then=();
|
||||
my @temp_now = localtime(time);
|
||||
$temp_now[4] = $cgiparams{'MONTH'};
|
||||
$temp_now[3] = $cgiparams{'DAY'};
|
||||
if ($cgiparams{'DAY'}) {
|
||||
@temp_then = localtime(POSIX::mktime(@temp_now) - 86400);
|
||||
## Retrieve the same time on the next day -
|
||||
## 86400 seconds in a day
|
||||
} else {
|
||||
$temp_now[3] = 1;
|
||||
$temp_now[4] = ($temp_now[4]-1) %12;
|
||||
@temp_then = localtime(POSIX::mktime(@temp_now) );
|
||||
$temp_then[3] = 0;
|
||||
}
|
||||
$cgiparams{'MONTH'} = $temp_then[4];
|
||||
$cgiparams{'DAY'} = $temp_then[3];
|
||||
}
|
||||
|
||||
# Find in which file.gz is the log. Can be calculated because WEEKLY ROTATING of access.log
|
||||
my $gzindex;
|
||||
my $date = $cgiparams{'DAY'} == 0 ? '' : $cgiparams{'DAY'} <= 9 ? "0$cgiparams{'DAY'}" : "$cgiparams{'DAY'}";
|
||||
|
||||
{
|
||||
my $xday;
|
||||
|
||||
# Calculate time. If future date, calculate for past year !!!
|
||||
if (( $cgiparams{'MONTH'} eq $now[4]) && ($cgiparams{'DAY'} > $now[3]) ||
|
||||
( $cgiparams{'MONTH'} > $now[4] ) ) {
|
||||
$xday = POSIX::mktime( 0, 0, 0, $cgiparams{'DAY'}, $cgiparams{'MONTH'}, $year - 1901 );
|
||||
$date = "$longmonths[$cgiparams{'MONTH'}] $date, ". int($year-1);
|
||||
} else {
|
||||
$xday = POSIX::mktime( 0, 0, 0, $cgiparams{'DAY'}, $cgiparams{'MONTH'}, $year - 1900 );
|
||||
$date = "$longmonths[$cgiparams{'MONTH'}] $date, $year";
|
||||
}
|
||||
|
||||
# calculate end of active week (saturday 23H59)
|
||||
my @then = ();
|
||||
@then = localtime(time());
|
||||
my $sunday = POSIX::mktime( 0, 0, 0, @then[3], @then[4], @then[5]);
|
||||
$sunday += (6-$then[6]) * 86400;
|
||||
|
||||
# Convert delta in second to full weeks
|
||||
$gzindex = int (($sunday-$xday)/604800 );
|
||||
}
|
||||
|
||||
my $monthstr = $shortmonths[$cgiparams{'MONTH'}];
|
||||
my $daystr = $cgiparams{'DAY'} == 0 ? '..' : $cgiparams{'DAY'} <= 9 ? " $cgiparams{'DAY'}" : "$cgiparams{'DAY'}";
|
||||
|
||||
my $lines = 0;
|
||||
my @log=();
|
||||
|
||||
my $loop = 1;
|
||||
my $filestr = 0;
|
||||
my $lastdatetime; # for debug
|
||||
my $search_for_end = 0;
|
||||
|
||||
while ($gzindex >=0 && $loop) {
|
||||
# calculate file name
|
||||
if ($gzindex == 0) {
|
||||
$filestr = "/var/log/messages";
|
||||
} else {
|
||||
$filestr = "/var/log/messages.$gzindex";
|
||||
$filestr = "$filestr.gz" if -f "$filestr.gz";
|
||||
}
|
||||
# now read file if existing
|
||||
if (open (FILE,($filestr =~ /.gz$/ ? "gzip -dc $filestr |" : $filestr))) {
|
||||
#&General::log("reading $filestr");
|
||||
READ:while (<FILE>) {
|
||||
my $line = $_;
|
||||
if ($line =~ /^${monthstr} ${daystr} ..:..:.. [\w\-]+ sni_logger\[\d+\]:.*$/) {
|
||||
# when standart viewing, just keep in memory the correct slice
|
||||
# it starts a '$start' and size is $viewport
|
||||
# If export, then keep all lines...
|
||||
if ($cgiparams{'ACTION'} eq $Lang::tr{'export'}){
|
||||
$log[$lines++] = "$line";
|
||||
} else {
|
||||
if ($lines++ < ($start + $Header::viewsize)) {
|
||||
push(@log,"$line");
|
||||
if (@log > $Header::viewsize) {
|
||||
shift (@log);
|
||||
}
|
||||
#} else { dont do this optimisation, need to count lines !
|
||||
# $datetime = $maxtime; # we have read viewsize lines, stop main loop
|
||||
# last READ; # exit read file
|
||||
}
|
||||
}
|
||||
$search_for_end = 1; # we find the start of slice, can look for end now
|
||||
} else {
|
||||
if ($search_for_end == 1) {
|
||||
#finish read files when date is over (test month equality only)
|
||||
$line =~ /^(...) (..) ..:..:..*$/;
|
||||
$loop = 0 if ( ($1 ne $monthstr) || ( ($daystr ne '..') && ($daystr ne $2) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
close (FILE);
|
||||
}
|
||||
$gzindex--; # will try next gz file eg 40,39,38,.... because it may have holes when ipcop stopped
|
||||
# for a long time
|
||||
}# while
|
||||
|
||||
# $errormessage = "$Lang::tr{'date not in logs'}: $filestr $Lang::tr{'could not be opened'}";
|
||||
|
||||
if ($cgiparams{'ACTION'} eq $Lang::tr{'export'})
|
||||
{
|
||||
print "Content-type: text/plain\n\n";
|
||||
print "BPFire XDP TLS/SSL Web Access log\r\n";
|
||||
print "$Lang::{'date'}: $date\r\n\r\n";
|
||||
|
||||
if ($logsettings{'LOGVIEW_REVERSE'} eq 'on') { @log = reverse @log; }
|
||||
|
||||
foreach $_ (@log)
|
||||
{
|
||||
/^... (..) (..:..:..) [\w\-]+ sni_logger\[\d+\]: Received SNI: (.*) from source IP: (.*)$/;
|
||||
my $day = $1;
|
||||
$day =~ tr / /0/;
|
||||
my $time = $cgiparams{'DAY'} ? "$2" : "$day/$2" ;
|
||||
my $domain = $3;
|
||||
print "$time $domain $4\r\n";
|
||||
|
||||
}
|
||||
exit 0;
|
||||
}
|
||||
|
||||
&Header::showhttpheaders();
|
||||
|
||||
&Header::openpage($Lang::tr{'xdpsni log'}, 1, '');
|
||||
|
||||
&Header::openbigbox('100%', 'left', '', $errormessage);
|
||||
|
||||
if ($errormessage) {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'error messages'});
|
||||
print "<font class='base'>$errormessage </font>\n";
|
||||
&Header::closebox();
|
||||
}
|
||||
|
||||
&Header::openbox('100%', 'left', "$Lang::tr{'settings'}");
|
||||
|
||||
print <<END
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td width='10%' class='base'>$Lang::tr{'month'}: </td>
|
||||
<td width='10%'>
|
||||
<select name='MONTH'>
|
||||
END
|
||||
;
|
||||
for (my $month = 0; $month < 12; $month++)
|
||||
{
|
||||
print "\t<option ";
|
||||
if ($month == $cgiparams{'MONTH'}) {
|
||||
print "selected='selected' ";
|
||||
}
|
||||
print "value='$month'>$longmonths[$month]</option>\n";
|
||||
}
|
||||
print <<END
|
||||
</select>
|
||||
</td>
|
||||
<td width='10%' class='base' align='right'> $Lang::tr{'day'}: </td>
|
||||
<td width='40%'>
|
||||
<select name='DAY'>
|
||||
END
|
||||
;
|
||||
print "<option value='0'>$Lang::tr{'all'}</option>\n";
|
||||
for (my $day = 1; $day <= 31; $day++)
|
||||
{
|
||||
print "\t<option ";
|
||||
if ($day == $cgiparams{'DAY'}) {
|
||||
print "selected='selected' ";
|
||||
}
|
||||
print "value='$day'>$day</option>\n";
|
||||
}
|
||||
print <<END
|
||||
</select>
|
||||
</td>
|
||||
<td width='5%' align='center'><input type='submit' name='ACTION' title='$Lang::tr{'day before'}' value='<<' /></td>
|
||||
<td width='5%' align='center'><input type='submit' name='ACTION' title='$Lang::tr{'day after'}' value='>>' /></td>
|
||||
<td width='10%' align='center'><input type='submit' name='ACTION' value='$Lang::tr{'update'}' /></td>
|
||||
<td width='10%' align='center'><input type='submit' name='ACTION' value='$Lang::tr{'export'}' /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
END
|
||||
;
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'log'});
|
||||
print "<p><b>$Lang::tr{'xdpsni hits'} $date: $lines</b></p>";
|
||||
|
||||
my $lastPageIndex = $lines - ${Header::viewsize};
|
||||
$start = $lastPageIndex if ($start >= $lastPageIndex);
|
||||
$start = 0 if ($start < 0);
|
||||
|
||||
my $prev;
|
||||
if ($start == 0) {
|
||||
$prev = -1;
|
||||
} else {
|
||||
$prev = $start - ${Header::viewsize};
|
||||
$prev = 0 if ( $prev < 0);
|
||||
}
|
||||
|
||||
my $next;
|
||||
if ($start == $lastPageIndex) {
|
||||
$next = -1;
|
||||
} else {
|
||||
$next = $start + ${Header::viewsize};
|
||||
$next = $lines - ${Header::viewsize} if ($next >= $lines - ${Header::viewsize});
|
||||
}
|
||||
|
||||
if ($logsettings{'LOGVIEW_REVERSE'} eq 'on') { @log = reverse @log; }
|
||||
if ($lines != 0) { &oldernewer(); }
|
||||
|
||||
print <<END
|
||||
<table width='100%' class='tbl'>
|
||||
<tr>
|
||||
<th align='center' class='boldbase'><b>$Lang::tr{'time'}</b></th>
|
||||
<th align='center' class='boldbase'><b>$Lang::tr{'domain name'}</b></th>
|
||||
<th align='center' class='boldbase'><b>$Lang::tr{'source'}</b></th>
|
||||
</tr>
|
||||
END
|
||||
;
|
||||
|
||||
|
||||
$lines = 0;
|
||||
foreach $_ (@log)
|
||||
{
|
||||
my ($day, $time, $domain, $srcaddr);
|
||||
if ($_ =~ /^... (..) (..:..:..) [\w\-]+ sni_logger\[\d+\]: Received SNI: (.*) from source IP: (.*)$/) {
|
||||
$day = $1;
|
||||
$day =~ tr / /0/;
|
||||
$time = $cgiparams{'DAY'} ? "$2" : "$day/$2" ;
|
||||
$domain = $3;
|
||||
$srcaddr = $4;
|
||||
|
||||
}
|
||||
|
||||
my $col="";
|
||||
if ($lines % 2) {
|
||||
print "<tr>";
|
||||
$col="bgcolor='$color{'color20'}'";
|
||||
}
|
||||
else {
|
||||
print "<tr>";
|
||||
$col="bgcolor='$color{'color22'}'";
|
||||
}
|
||||
print <<END
|
||||
|
||||
<td align='center' $col>$time</td>
|
||||
<td align='center' $col>$domain</td>
|
||||
<td align='center' $col>$srcaddr</td>
|
||||
END
|
||||
;
|
||||
print <<END
|
||||
</tr>
|
||||
END
|
||||
;
|
||||
$lines++;
|
||||
}
|
||||
|
||||
print "</table>";
|
||||
|
||||
&oldernewer();
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::closebigbox();
|
||||
|
||||
&Header::closepage();
|
||||
|
||||
sub oldernewer
|
||||
{
|
||||
print <<END
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
END
|
||||
;
|
||||
|
||||
print "<td align='center' width='50%'>";
|
||||
if ($prev != -1) {
|
||||
print "<a href='/cgi-bin/logs.cgi/xdpsnilog.dat?0,$cgiparams{'MONTH'},$cgiparams{'DAY'}'>$Lang::tr{'first'}</a> ";
|
||||
print "<a href='/cgi-bin/logs.cgi/xdpsnilog.dat?$prev,$cgiparams{'MONTH'},$cgiparams{'DAY'}'>$Lang::tr{'older'}</a>";
|
||||
}
|
||||
else {
|
||||
print "$Lang::tr{'first'} $Lang::tr{'older'}";
|
||||
}
|
||||
print "</td>\n";
|
||||
|
||||
print "<td align='center' width='50%'>";
|
||||
if ($next >= 0) {
|
||||
print "<a href='/cgi-bin/logs.cgi/xdpsnilog.dat?$next,$cgiparams{'MONTH'},$cgiparams{'DAY'}'>$Lang::tr{'newer'}</a> ";
|
||||
print "<a href='/cgi-bin/logs.cgi/xdpsnilog.dat?$lastPageIndex,$cgiparams{'MONTH'},$cgiparams{'DAY'}'>$Lang::tr{'last'}</a>";
|
||||
}
|
||||
else {
|
||||
print "$Lang::tr{'newer'} $Lang::tr{'last'} ";
|
||||
}
|
||||
print "</td>\n";
|
||||
|
||||
print <<END
|
||||
</tr>
|
||||
</table>
|
||||
END
|
||||
;
|
||||
}
|
||||
|
||||
480
html/cgi-bin/loxilb.cgi
Normal file
480
html/cgi-bin/loxilb.cgi
Normal file
@@ -0,0 +1,480 @@
|
||||
#!/usr/bin/perl
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2020 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2024 BPFire <vincent.mc.li@gmail.com> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
use strict;
|
||||
|
||||
# enable only the following on debugging purpose
|
||||
use warnings;
|
||||
use CGI::Carp 'fatalsToBrowser';
|
||||
|
||||
use IO::Socket;
|
||||
|
||||
require '/var/ipfire/general-functions.pl';
|
||||
require "${General::swroot}/location-functions.pl";
|
||||
require "${General::swroot}/lang.pl";
|
||||
require "${General::swroot}/header.pl";
|
||||
|
||||
#workaround to suppress a warning when a variable is used only once
|
||||
my @dummy = ( ${Header::colouryellow} );
|
||||
undef (@dummy);
|
||||
|
||||
my %color = ();
|
||||
my %mainsettings = ();
|
||||
my %settings=();
|
||||
my %checked=();
|
||||
my $errormessage='';
|
||||
my $setting = "${General::swroot}/main/settings";
|
||||
my $loxilbsettingfile = "${General::swroot}/loxilb/settings";
|
||||
my $loxilbipfile = "${General::swroot}/loxilb/ipconfigfile";
|
||||
|
||||
# Read configuration file.
|
||||
|
||||
&General::readhash("${General::swroot}/main/settings", \%mainsettings);
|
||||
&General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", \%color);
|
||||
|
||||
&Header::showhttpheaders();
|
||||
|
||||
$settings{'ENABLE_LOXILB'} = 'off';
|
||||
$settings{'ACTION'} = '';
|
||||
|
||||
$settings{'KEY1'} = ''; # point record for ACTION
|
||||
$settings{'virtualIP'} = '';
|
||||
$settings{'interface'} = '';
|
||||
my @nosaved=('virtualIP','interface', 'KEY1', 'SORT_virtualIPLIST');
|
||||
|
||||
#Define each field that can be used to sort columns
|
||||
my $sortstring='^virtualIP';
|
||||
$settings{'SORT_virtualIPLIST'} = 'virtualIP';
|
||||
|
||||
# Load multiline data
|
||||
our @current = ();
|
||||
if (open(FILE, "$loxilbipfile")) {
|
||||
@current = <FILE>;
|
||||
close (FILE);
|
||||
}
|
||||
|
||||
&Header::getcgihash(\%settings);
|
||||
|
||||
if ($settings{'ACTION'} eq $Lang::tr{'save'})
|
||||
{
|
||||
|
||||
map (delete ($settings{$_}) ,(@nosaved));
|
||||
&General::writehash("$loxilbsettingfile", \%settings);
|
||||
|
||||
if ($settings{'ENABLE_LOXILB'} eq 'on') {
|
||||
&General::system('/usr/bin/touch', "${General::swroot}/loxilb/enableloxilb");
|
||||
&General::system('/usr/local/bin/loxilbctrl', 'start');
|
||||
} else {
|
||||
&General::system('/usr/local/bin/loxilbctrl', 'stop');
|
||||
unlink "${General::swroot}/loxilb/enableloxilb";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($settings{'ACTION'} eq $Lang::tr{'add'}) {
|
||||
# Validate inputs
|
||||
if (!&General::validipandmask($settings{'virtualIP'})){
|
||||
$errormessage = $Lang::tr{'invalid ip'}." / ".$Lang::tr{'invalid netmask'};
|
||||
}
|
||||
|
||||
#Check for already existing routing entry
|
||||
foreach my $line (@current) {
|
||||
chomp($line); # remove newline
|
||||
my @temp=split(/\,/,$line);
|
||||
$temp[1] ='' unless defined $temp[1]; # interface
|
||||
#Same ip already used?
|
||||
if($temp[0] eq $settings{'virtualIP'} && $settings{'KEY1'} eq ''){
|
||||
$errormessage = $Lang::tr{'ccd err loxilbconfigeexist'};
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
unless ($errormessage) {
|
||||
if ($settings{'KEY1'} eq '') { #add or edit ?
|
||||
unshift (@current, "$settings{'virtualIP'},$settings{'interface'}\n");
|
||||
&General::log($Lang::tr{'loxilb lb config added'});
|
||||
} else {
|
||||
@current[$settings{'KEY1'}] = "$settings{'virtualIP'},$settings{'interface'}\n";
|
||||
$settings{'KEY1'} = ''; # End edit mode
|
||||
&General::log($Lang::tr{'loxilb fw changed'});
|
||||
}
|
||||
|
||||
&CreateIP(%settings);
|
||||
|
||||
# Write changes to config file.
|
||||
&SortDataFile; # sort newly added/modified entry
|
||||
|
||||
#map ($settings{$_}='' ,@nosaved); # Clear fields
|
||||
}
|
||||
}
|
||||
|
||||
if ($settings{'ACTION'} eq $Lang::tr{'remove'}) {
|
||||
|
||||
my $line = @current[$settings{'KEY1'}]; # KEY1 is the index in current
|
||||
chomp($line);
|
||||
my @temp = split(/\,/, $line);
|
||||
$settings{'virtualIP'}=$temp[0];
|
||||
$settings{'interface'}=$temp[1];
|
||||
|
||||
&DeleteIP(%settings);
|
||||
|
||||
splice (@current,$settings{'KEY1'},1); # Delete line
|
||||
open(FILE, ">$loxilbipfile") or die "$loxilbipfile open error";
|
||||
print FILE @current;
|
||||
close(FILE);
|
||||
$settings{'KEY1'} = ''; # End remove mode
|
||||
}
|
||||
|
||||
## Check if sorting is asked
|
||||
# If same column clicked, reverse the sort.
|
||||
if ($ENV{'QUERY_STRING'} =~ /$sortstring/ ) {
|
||||
my $newsort=$ENV{'QUERY_STRING'};
|
||||
my $actual=$settings{'SORT_virtualIPLIST'};
|
||||
#Reverse actual sort ?
|
||||
if ($actual =~ $newsort) {
|
||||
my $Rev='';
|
||||
if ($actual !~ 'Rev') {
|
||||
$Rev='Rev';
|
||||
}
|
||||
$newsort.=$Rev;
|
||||
}
|
||||
$settings{'SORT_virtualIPLIST'}=$newsort;
|
||||
map (delete ($settings{$_}) ,(@nosaved,'ACTION','KEY1'));# Must never be saved
|
||||
&General::writehash($setting, \%settings);
|
||||
&SortDataFile;
|
||||
$settings{'ACTION'} = 'SORT'; # Create an 'ACTION'
|
||||
map ($settings{$_} = '' ,@nosaved,'KEY1'); # and reinit vars to empty
|
||||
}
|
||||
|
||||
if ($settings{'ACTION'} eq '' ) { # First launch from GUI
|
||||
# Place here default value when nothing is initialized
|
||||
$settings{'virtualIP'} = '';
|
||||
$settings{'interface'} = '';
|
||||
}
|
||||
|
||||
&Header::openpage($Lang::tr{'loxilb'}, 1, '');
|
||||
|
||||
&Header::openbigbox('100%', 'left', '', $errormessage);
|
||||
|
||||
if ($errormessage) {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'error messages'});
|
||||
print "<font class='base' color=red>$errormessage </font>\n";
|
||||
&Header::closebox();
|
||||
}
|
||||
|
||||
# Read configuration file.
|
||||
&General::readhash("$loxilbsettingfile", \%settings);
|
||||
|
||||
# Checkbox pre-selection.
|
||||
my $checked;
|
||||
if ($settings{'ENABLE_LOXILB'} eq "on") {
|
||||
$checked = "checked='checked'";
|
||||
}
|
||||
|
||||
my $sactive = "<table cellpadding='2' cellspacing='0' bgcolor='${Header::colourred}' width='50%'><tr><td align='center'><b><font color='#FFFFFF'>$Lang::tr{'stopped'}</font></b></td></tr></table>";
|
||||
|
||||
my @status = &General::system_output('/usr/local/bin/loxilbctrl', 'status');
|
||||
|
||||
if (grep(/is running/, @status)){
|
||||
$sactive = "<table cellpadding='2' cellspacing='0' bgcolor='${Header::colourgreen}' width='50%'><tr><td align='center'><b><font color='#FFFFFF'>$Lang::tr{'running'}</font></b></td></tr></table>";
|
||||
}
|
||||
|
||||
&Header::openbox('100%', 'center', $Lang::tr{'loxilb status'});
|
||||
|
||||
print <<END;
|
||||
<table width='100%'>
|
||||
<form method='POST' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<td width='25%'> </td>
|
||||
<td width='25%'> </td>
|
||||
<td width='25%'> </td>
|
||||
<tr><td class='boldbase'>$Lang::tr{'loxilb server status'}</td>
|
||||
<td align='left'>$sactive</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width='50%' class='boldbase'>$Lang::tr{'loxilb enable'}
|
||||
<td><input type='checkbox' name='ENABLE_LOXILB' $checked></td>
|
||||
<td align='center'><input type='submit' name='ACTION' value='$Lang::tr{'save'}'></td>
|
||||
</tr>
|
||||
END
|
||||
|
||||
print "</form> </table>\n";
|
||||
|
||||
&Header::closebox();
|
||||
#
|
||||
|
||||
my $buttontext = $Lang::tr{'add'};
|
||||
if ($settings{'KEY1'} ne '') {
|
||||
$buttontext = $Lang::tr{'update'};
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'loxilb fw edit'});
|
||||
} else {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'loxilb ip add'});
|
||||
}
|
||||
|
||||
my @INTERFACES = ("red0", "green0");
|
||||
|
||||
#Edited line number (KEY1) passed until cleared by 'save' or 'remove' or 'new sort order'
|
||||
print <<END;
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<input type='hidden' name='KEY1' value='$settings{'KEY1'}' />
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb ip virtualIP'}: </td>
|
||||
<td><input type='text' name='virtualIP' value='$settings{'virtualIP'}' size='25'/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb ip interface'}: </td>
|
||||
<td>
|
||||
<select name='interface' id='interface' style="width: 95px;">
|
||||
END
|
||||
|
||||
# Insert the dynamic options for the 'PROTO' select element
|
||||
foreach (@INTERFACES) {
|
||||
print "<option value=\"$_\"";
|
||||
if ($_ eq $settings{'interface'}) {
|
||||
print " selected=\"selected\"";
|
||||
}
|
||||
print ">$_</option>";
|
||||
}
|
||||
|
||||
print <<END;
|
||||
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td width='50%' align='right'><input type='hidden' name='ACTION' value='$Lang::tr{'add'}' /><input type='submit' name='SUBMIT' value='$buttontext' /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
END
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'loxilb ip entries'});
|
||||
|
||||
print <<END;
|
||||
|
||||
<table width='100%' class='tbl'>
|
||||
<tr>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?virtualIP'><b>$Lang::tr{'loxilb ip virtualIP'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?interface'><b>$Lang::tr{'loxilb ip interface'}</b></a></th>
|
||||
<th width='10%' colspan='3' class='boldbase' align='center'><b>$Lang::tr{'action'}</b></th>
|
||||
</tr>
|
||||
END
|
||||
|
||||
#
|
||||
# Print each line of @current list
|
||||
#
|
||||
|
||||
my $key = 0;
|
||||
my $col="";
|
||||
foreach my $line (@current) {
|
||||
chomp($line); # remove newline
|
||||
my @temp=split(/\,/,$line);
|
||||
$temp[1] ='' unless defined $temp[1]; # not always populated
|
||||
|
||||
#Choose icon for checkbox
|
||||
my $gif = '';
|
||||
my $gdesc = '';
|
||||
if ($temp[0] ne '' ) {
|
||||
$gif = 'on.gif';
|
||||
$gdesc = $Lang::tr{'click to disable'};
|
||||
} else {
|
||||
$gif = 'off.gif';
|
||||
$gdesc = $Lang::tr{'click to enable'};
|
||||
}
|
||||
|
||||
#Colorize each line
|
||||
if ($settings{'KEY1'} eq $key) {
|
||||
print "<tr bgcolor='${Header::colouryellow}'>";
|
||||
} elsif ($key % 2) {
|
||||
print "<tr>";
|
||||
$col="bgcolor='$color{'color20'}'";
|
||||
} else {
|
||||
print "<tr>";
|
||||
$col="bgcolor='$color{'color22'}'";
|
||||
}
|
||||
print <<END;
|
||||
<td align='center' $col>$temp[0]</td>
|
||||
<td align='center' $col>$temp[1]</td>
|
||||
<td align='center' $col>
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<input type='hidden' name='ACTION' value='$Lang::tr{'toggle enable disable'}' />
|
||||
<input type='image' name='$Lang::tr{'toggle enable disable'}' src='/images/$gif' alt='$gdesc' title='$gdesc' />
|
||||
<input type='hidden' name='KEY1' value='$key' />
|
||||
</form>
|
||||
</td>
|
||||
|
||||
<td align='center' $col>
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<input type='hidden' name='ACTION' value='$Lang::tr{'remove'}' />
|
||||
<input type='image' name='$Lang::tr{'remove'}' src='/images/delete.gif' alt='$Lang::tr{'remove'}' title='$Lang::tr{'remove'}' />
|
||||
<input type='hidden' name='KEY1' value='$key' />
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
END
|
||||
|
||||
$key++;
|
||||
}
|
||||
print "</table>";
|
||||
|
||||
# If table contains entries, print 'Key to action icons'
|
||||
if ($key) {
|
||||
print <<END;
|
||||
<table>
|
||||
<tr>
|
||||
<td class='boldbase'> <b>$Lang::tr{'legend'}: </b></td>
|
||||
<td><img src='/images/on.gif' alt='$Lang::tr{'click to disable'}' /></td>
|
||||
<td class='base'>$Lang::tr{'click to disable'}</td>
|
||||
<td> </td>
|
||||
<td><img src='/images/off.gif' alt='$Lang::tr{'click to enable'}' /></td>
|
||||
<td class='base'>$Lang::tr{'click to enable'}</td>
|
||||
<td> </td>
|
||||
<td><img src='/images/delete.gif' alt='$Lang::tr{'remove'}' /></td>
|
||||
<td class='base'>$Lang::tr{'remove'}</td>
|
||||
</tr>
|
||||
</table>
|
||||
END
|
||||
}
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::closebigbox();
|
||||
|
||||
&Header::closepage();
|
||||
|
||||
|
||||
## Ouf it's the end !
|
||||
|
||||
# Sort the "current" array according to choices
|
||||
sub SortDataFile
|
||||
{
|
||||
our %entries = ();
|
||||
|
||||
# Sort pair of record received in $a $b special vars.
|
||||
# When IP is specified use numeric sort else alpha.
|
||||
# If sortname ends with 'Rev', do reverse sort.
|
||||
#
|
||||
sub fixedleasesort {
|
||||
my $qs=''; # The sort field specified minus 'Rev'
|
||||
if (rindex ($settings{'SORT_virtualIPLIST'},'Rev') != -1) {
|
||||
$qs=substr ($settings{'SORT_virtualIPLIST'},0,length($settings{'SORT_virtualIPLIST'})-3);
|
||||
if ($qs eq 'virtualIP') {
|
||||
my @a = split(/\./,$entries{$a}->{$qs});
|
||||
my @b = split(/\./,$entries{$b}->{$qs});
|
||||
($b[0]<=>$a[0]) ||
|
||||
($b[1]<=>$a[1]) ||
|
||||
($b[2]<=>$a[2]) ||
|
||||
($b[3]<=>$a[3]);
|
||||
} else {
|
||||
$entries{$b}->{$qs} cmp $entries{$a}->{$qs};
|
||||
}
|
||||
} else { #not reverse
|
||||
$qs=$settings{'SORT_virtualIPLIST'};
|
||||
if ($qs eq 'virtualIP') {
|
||||
my @a = split(/\./,$entries{$a}->{$qs});
|
||||
my @b = split(/\./,$entries{$b}->{$qs});
|
||||
($a[0]<=>$b[0]) ||
|
||||
($a[1]<=>$b[1]) ||
|
||||
($a[2]<=>$b[2]) ||
|
||||
($a[3]<=>$b[3]);
|
||||
} else {
|
||||
$entries{$a}->{$qs} cmp $entries{$b}->{$qs};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Use an associative array (%entries)
|
||||
my $key = 0;
|
||||
foreach my $line (@current) {
|
||||
chomp( $line); #remove newline because can be on field 5 or 6 (addition of REMARK)
|
||||
my @temp = ( '','','', '');
|
||||
@temp = split (',',$line);
|
||||
|
||||
# Build a pair 'Field Name',value for each of the data dataline.
|
||||
# Each SORTABLE field must have is pair.
|
||||
# Other data fields (non sortable) can be grouped in one
|
||||
|
||||
my @record = ('KEY',$key++,'virtualIP',$temp[0],'interface',$temp[1]);
|
||||
my $record = {}; # create a reference to empty hash
|
||||
%{$record} = @record; # populate that hash with @record
|
||||
$entries{$record->{KEY}} = $record; # add this to a hash of hashes
|
||||
}
|
||||
|
||||
open(FILE, ">$loxilbipfile") or die "$loxilbipfile open error";
|
||||
|
||||
# Each field value is printed , with the newline ! Don't forget separator and order of them.
|
||||
foreach my $entry (sort fixedleasesort keys %entries) {
|
||||
print FILE "$entries{$entry}->{virtualIP},$entries{$entry}->{interface}\n";
|
||||
}
|
||||
|
||||
close(FILE);
|
||||
# Reload sorted @current
|
||||
open (FILE, "$loxilbipfile");
|
||||
@current = <FILE>;
|
||||
close (FILE);
|
||||
}
|
||||
|
||||
sub manageIP {
|
||||
my ($action, %settings) = @_;
|
||||
|
||||
# Initialize variables
|
||||
my @loxicmd_options;
|
||||
my $command = 'loxicmd';
|
||||
|
||||
my $ip = $settings{'virtualIP'};
|
||||
my $interface = $settings{'interface'};
|
||||
|
||||
push(@loxicmd_options, $action, "ip", $ip, $interface);
|
||||
|
||||
#debug and display output in UI
|
||||
#my @output = &General::system_output($command, @loxicmd_options);
|
||||
#$errormessage = join('', @output);
|
||||
&General::system($command, @loxicmd_options);
|
||||
|
||||
}
|
||||
|
||||
sub SaveIP {
|
||||
my @save_options;
|
||||
my $command = 'loxicmd';
|
||||
my $dir="/var/ipfire/loxilb/";
|
||||
push(@save_options, "save", "--ip", "-c", $dir);
|
||||
&General::system_output($command, @save_options);
|
||||
#my @output = &General::system_output($command, @save_options);
|
||||
#$errormessage = join('', @output);
|
||||
}
|
||||
|
||||
sub CreateIP {
|
||||
my (%settings) = @_;
|
||||
manageIP("create", %settings);
|
||||
&SaveIP;
|
||||
}
|
||||
|
||||
sub DeleteIP {
|
||||
my (%settings) = @_;
|
||||
manageIP("delete", %settings);
|
||||
&SaveIP;
|
||||
}
|
||||
711
html/cgi-bin/loxilbconfig.cgi
Normal file
711
html/cgi-bin/loxilbconfig.cgi
Normal file
@@ -0,0 +1,711 @@
|
||||
#!/usr/bin/perl
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2011 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2024 BPFire Team #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
use strict;
|
||||
|
||||
# enable only the following on debugging purpose
|
||||
use warnings;
|
||||
#use CGI::Carp 'fatalsToBrowser';
|
||||
|
||||
require '/var/ipfire/general-functions.pl';
|
||||
require "${General::swroot}/lang.pl";
|
||||
require "${General::swroot}/header.pl";
|
||||
|
||||
#workaround to suppress a warning when a variable is used only once
|
||||
my @dummy = ( ${Header::colouryellow} );
|
||||
undef (@dummy);
|
||||
|
||||
# Files used
|
||||
my $setting = "${General::swroot}/main/settings";
|
||||
our $datafile = "${General::swroot}/loxilb/lbconfig"; #(our: used in subroutine)
|
||||
my $loxilbipfile = "${General::swroot}/loxilb/ipconfigfile";
|
||||
my $redfile = "${General::swroot}/red/local-ipaddress";
|
||||
|
||||
our @REDIP = ();
|
||||
our @IPFILE = ();
|
||||
|
||||
if (open(FILE, "$redfile")) {
|
||||
@REDIP = <FILE>;
|
||||
close (FILE);
|
||||
}
|
||||
|
||||
if (open(FILE, "$loxilbipfile")) {
|
||||
@IPFILE = <FILE>;
|
||||
close (FILE);
|
||||
}
|
||||
|
||||
my %color = ();
|
||||
my %mainsettings = ();
|
||||
&General::readhash("${General::swroot}/main/settings", \%mainsettings);
|
||||
&General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", \%color);
|
||||
|
||||
our %settings = ();
|
||||
|
||||
$settings{'EN'} = ''; # reuse for dummy field in position zero
|
||||
$settings{'NAME'} = '';
|
||||
$settings{'EXTIP'} = '';
|
||||
$settings{'PORT'} = '';
|
||||
$settings{'PROTO'} = '';
|
||||
$settings{'SEL'} = '';
|
||||
$settings{'MODE'} = '';
|
||||
$settings{'ENDPOINTS'} = '';
|
||||
$settings{'EPORT'} = '';
|
||||
$settings{'MONITOR'} = '';
|
||||
my @nosaved=('EN','NAME','EXTIP','PORT','PROTO','SEL','MODE','ENDPOINTS','EPORT','MONITOR'); # List here ALL setting2 fields. Mandatory
|
||||
|
||||
$settings{'ACTION'} = ''; # add/edit/remove
|
||||
$settings{'KEY1'} = ''; # point record for ACTION
|
||||
|
||||
#Define each field that can be used to sort columns
|
||||
my $sortstring='^NAME';
|
||||
$settings{'SORT_NAMELIST'} = 'NAME';
|
||||
my $errormessage = '';
|
||||
my $warnmessage = '';
|
||||
|
||||
&Header::showhttpheaders();
|
||||
|
||||
#Get GUI values
|
||||
&Header::getcgihash(\%settings);
|
||||
|
||||
###############
|
||||
# DEBUG DEBUG
|
||||
#&Header::openbox('100%', 'left', 'DEBUG');
|
||||
#my $debugCount = 0;
|
||||
#foreach my $line (sort keys %settings) {
|
||||
#print "$line = $settings{$line}<br />\n";
|
||||
# $debugCount++;
|
||||
#}
|
||||
#print " Count: $debugCount\n";
|
||||
#&Header::closebox();
|
||||
# DEBUG DEBUG
|
||||
###############
|
||||
|
||||
# Load multiline data
|
||||
our @current = ();
|
||||
if (open(FILE, "$datafile")) {
|
||||
@current = <FILE>;
|
||||
close (FILE);
|
||||
}
|
||||
|
||||
## Settings1 Box not used...
|
||||
&General::readhash("${General::swroot}/main/settings", \%settings);
|
||||
|
||||
|
||||
## Now manipulate the multi-line list with Settings2
|
||||
# Basic actions are:
|
||||
# toggle the check box
|
||||
# add/update a new line
|
||||
# begin editing a line
|
||||
# remove a line
|
||||
|
||||
|
||||
# Toggle enable/disable field. Field is in second position
|
||||
if ($settings{'ACTION'} eq $Lang::tr{'toggle enable disable'}) {
|
||||
#move out new line
|
||||
chomp(@current[$settings{'KEY1'}]);
|
||||
my @temp = split(/\,/,@current[$settings{'KEY1'}]);
|
||||
|
||||
$temp[0] = $temp[0] ne '' ? '' : 'on'; # Toggle the field
|
||||
@current[$settings{'KEY1'}] = join (',',@temp)."\n";
|
||||
$settings{'KEY1'} = ''; # End edit mode
|
||||
|
||||
&General::log($Lang::tr{'loxilb lb config changed'});
|
||||
|
||||
#Save current
|
||||
open(FILE, ">$datafile") or die 'loxilb lbconfig datafile error';
|
||||
print FILE @current;
|
||||
close(FILE);
|
||||
|
||||
# Rebuild configuration file
|
||||
#&BuildConfiguration;
|
||||
}
|
||||
|
||||
if ($settings{'ACTION'} eq $Lang::tr{'add'}) {
|
||||
# Validate inputs
|
||||
if (!&General::validip($settings{'EXTIP'})){
|
||||
$errormessage = $Lang::tr{'invalid ip'};
|
||||
}
|
||||
|
||||
if ($settings{'EXTIP'} =~ /^0\.0\.0\.0/){
|
||||
$errormessage = $Lang::tr{'invalid ip'}." - 0.0.0.0";
|
||||
}
|
||||
if ($settings{'NAME'} eq ''){
|
||||
$errormessage = "LB Name: ".$Lang::tr{'loxilb empty'};
|
||||
}
|
||||
|
||||
# Escape input in REMARK field
|
||||
$settings{'NAME'} = &Header::escape($settings{'NAME'});
|
||||
|
||||
#Check for already existing routing entry
|
||||
foreach my $line (@current) {
|
||||
chomp($line); # remove newline
|
||||
my @temp=split(/\,/,$line);
|
||||
$temp[2] ='' unless defined $temp[2]; # not always populated
|
||||
$temp[3] ='' unless defined $temp[2]; # not always populated
|
||||
$temp[4] ='' unless defined $temp[3]; # not always populated
|
||||
$temp[5] ='' unless defined $temp[4]; # not always populated
|
||||
$temp[6] ='' unless defined $temp[5]; # not always populated
|
||||
$temp[7] ='' unless defined $temp[6]; # not always populated
|
||||
$temp[8] ='' unless defined $temp[7]; # not always populated
|
||||
$temp[9] ='' unless defined $temp[8]; # not always populated
|
||||
#Same ip already used?
|
||||
if($temp[1] eq $settings{'NAME'} && $settings{'KEY1'} eq ''){
|
||||
$errormessage = $Lang::tr{'ccd err loxilbconfigeexist'};
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
unless ($errormessage) {
|
||||
if ($settings{'KEY1'} eq '') { #add or edit ?
|
||||
unshift (@current, "$settings{'EN'},$settings{'NAME'},$settings{'EXTIP'},$settings{'PORT'},$settings{'PROTO'},$settings{'SEL'},$settings{'MODE'},$settings{'ENDPOINTS'},$settings{'EPORT'},$settings{'MONITOR'}\n");
|
||||
&General::log($Lang::tr{'loxilb lb config added'});
|
||||
} else {
|
||||
@current[$settings{'KEY1'}] = "$settings{'EN'},$settings{'NAME'},$settings{'EXTIP'},$settings{'PORT'},$settings{'PROTO'},$settings{'SEL'},$settings{'MODE'},$settings{'ENDPOINTS'},$settings{'EPORT'},$settings{'MONITOR'}\n";
|
||||
$settings{'KEY1'} = ''; # End edit mode
|
||||
&General::log($Lang::tr{'loxilb lb config changed'});
|
||||
}
|
||||
|
||||
if ($settings{'EN'} eq 'on') {
|
||||
&CreateLB(%settings);
|
||||
}
|
||||
|
||||
# Write changes to config file.
|
||||
&SortDataFile; # sort newly added/modified entry
|
||||
|
||||
#map ($settings{$_}='' ,@nosaved); # Clear fields
|
||||
}
|
||||
}
|
||||
|
||||
if ($settings{'ACTION'} eq $Lang::tr{'edit'}) {
|
||||
#move out new line
|
||||
my $line = @current[$settings{'KEY1'}]; # KEY1 is the index in current
|
||||
chomp($line);
|
||||
my @temp = split(/\,/, $line);
|
||||
$settings{'EN'}=$temp[0]; # Prepare the screen for editing
|
||||
$settings{'NAME'}=$temp[1];
|
||||
$settings{'EXTIP'}=$temp[2];
|
||||
$settings{'PORT'}=$temp[3];
|
||||
$settings{'PROTO'}=$temp[4];
|
||||
$settings{'SEL'}=$temp[5];
|
||||
$settings{'MODE'}=$temp[6];
|
||||
$settings{'ENDPOINTS'}=$temp[7];
|
||||
$settings{'EPORT'}=$temp[8];
|
||||
$settings{'MONITOR'}=$temp[9];
|
||||
if ($settings{'EN'} eq 'on') {
|
||||
&CreateLB(%settings);
|
||||
}
|
||||
}
|
||||
|
||||
if ($settings{'ACTION'} eq $Lang::tr{'remove'}) {
|
||||
|
||||
my $line = @current[$settings{'KEY1'}]; # KEY1 is the index in current
|
||||
chomp($line);
|
||||
my @temp = split(/\,/, $line);
|
||||
$settings{'EN'}=$temp[0]; # Prepare the screen for editing
|
||||
$settings{'NAME'}=$temp[1];
|
||||
$settings{'EXTIP'}=$temp[2];
|
||||
$settings{'PORT'}=$temp[3];
|
||||
$settings{'PROTO'}=$temp[4];
|
||||
$settings{'SEL'}=$temp[5];
|
||||
$settings{'MODE'}=$temp[6];
|
||||
$settings{'ENDPOINTS'}=$temp[7];
|
||||
$settings{'EPORT'}=$temp[8];
|
||||
$settings{'MONITOR'}=$temp[9];
|
||||
&DeleteLB(%settings);
|
||||
|
||||
splice (@current,$settings{'KEY1'},1); # Delete line
|
||||
open(FILE, ">$datafile") or die 'route datafile error';
|
||||
print FILE @current;
|
||||
close(FILE);
|
||||
$settings{'KEY1'} = ''; # End remove mode
|
||||
&General::log($Lang::tr{'loxilb lb config changed'});
|
||||
|
||||
#&BuildConfiguration; # then re-build conf which use new data
|
||||
}
|
||||
|
||||
## Check if sorting is asked
|
||||
# If same column clicked, reverse the sort.
|
||||
if ($ENV{'QUERY_STRING'} =~ /$sortstring/ ) {
|
||||
my $newsort=$ENV{'QUERY_STRING'};
|
||||
my $actual=$settings{'SORT_NAMELIST'};
|
||||
#Reverse actual sort ?
|
||||
if ($actual =~ $newsort) {
|
||||
my $Rev='';
|
||||
if ($actual !~ 'Rev') {
|
||||
$Rev='Rev';
|
||||
}
|
||||
$newsort.=$Rev;
|
||||
}
|
||||
$settings{'SORT_NAMELIST'}=$newsort;
|
||||
map (delete ($settings{$_}) ,(@nosaved,'ACTION','KEY1'));# Must never be saved
|
||||
&General::writehash($setting, \%settings);
|
||||
&SortDataFile;
|
||||
$settings{'ACTION'} = 'SORT'; # Create an 'ACTION'
|
||||
map ($settings{$_} = '' ,@nosaved,'KEY1'); # and reinit vars to empty
|
||||
}
|
||||
|
||||
if ($settings{'ACTION'} eq '' ) { # First launch from GUI
|
||||
# Place here default value when nothing is initialized
|
||||
$settings{'EN'} = 'on';
|
||||
$settings{'NAME'} = '';
|
||||
$settings{'EXTIP'} = '';
|
||||
$settings{'PORT'} = '';
|
||||
$settings{'PROTO'} = '';
|
||||
$settings{'SEL'} = '';
|
||||
$settings{'MODE'} = '';
|
||||
$settings{'ENDPOINTS'} = '';
|
||||
$settings{'EPORT'} = '';
|
||||
$settings{'MONITOR'} = '';
|
||||
}
|
||||
|
||||
&Header::openpage($Lang::tr{'loxilb lb config entries'}, 1, '');
|
||||
&Header::openbigbox('100%', 'left', '', $errormessage);
|
||||
my %checked=(); # Checkbox manipulations
|
||||
|
||||
if ($errormessage) {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'error messages'});
|
||||
print "<font class='base' color=red>$errormessage </font>";
|
||||
&Header::closebox();
|
||||
}
|
||||
|
||||
#
|
||||
|
||||
$checked{'EN'}{'on'} = ($settings{'EN'} eq '' ) ? '' : "checked='checked'";
|
||||
|
||||
my $buttontext = $Lang::tr{'add'};
|
||||
if ($settings{'KEY1'} ne '') {
|
||||
$buttontext = $Lang::tr{'update'};
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'loxilb lb edit'});
|
||||
} else {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'loxilb lb add'});
|
||||
}
|
||||
|
||||
my @PROTOCOLS = ("tcp", "udp");
|
||||
my @ALGO = ("rr", "hash", "priority", "persist", "lc");
|
||||
my @MODE = ("default", "onearm", "fullnat", "dsr");
|
||||
my @MONITOR = ("on", "off");
|
||||
my @VIP;
|
||||
push(@VIP, @REDIP);
|
||||
|
||||
foreach my $line (@IPFILE) {
|
||||
chomp($line);
|
||||
my @temp = split(/\,/, $line);
|
||||
if ($temp[1] eq "red0") {
|
||||
my @tmp = split(/\//, $temp[0]);
|
||||
push(@VIP, $tmp[0]);
|
||||
}
|
||||
}
|
||||
|
||||
#Edited line number (KEY1) passed until cleared by 'save' or 'remove' or 'new sort order'
|
||||
print <<END;
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<input type='hidden' name='KEY1' value='$settings{'KEY1'}' />
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb lb name'} <img src='/blob.gif' alt='*' /></td>
|
||||
<td><input type='text' name='NAME' value='$settings{'NAME'}' size='25'/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb lb extip'}: </td>
|
||||
<td>
|
||||
<select name='EXTIP' id='extip' style="width: 95px;">
|
||||
END
|
||||
|
||||
foreach (@VIP) {
|
||||
print "<option value=\"$_\"";
|
||||
if ($_ eq $settings{'EXTIP'}) {
|
||||
print " selected=\"selected\"";
|
||||
}
|
||||
print ">$_</option>";
|
||||
}
|
||||
|
||||
print <<END;
|
||||
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<td class='base'>$Lang::tr{'enabled'}</td>
|
||||
<td><input type='checkbox' name='EN' $checked{'EN'}{'on'} /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb lb port'} <img src='/blob.gif' alt='*' /></td>
|
||||
<td><input type='text' name='PORT' value='$settings{'PORT'}' size='25'/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb lb proto'}: </td>
|
||||
<td>
|
||||
<select name='PROTO' id='protocol' style="width: 95px;">
|
||||
END
|
||||
|
||||
# Insert the dynamic options for the 'PROTO' select element
|
||||
foreach (@PROTOCOLS) {
|
||||
print "<option value=\"$_\"";
|
||||
if ($_ eq $settings{'PROTO'}) {
|
||||
print " selected=\"selected\"";
|
||||
}
|
||||
print ">$_</option>";
|
||||
}
|
||||
|
||||
print <<END;
|
||||
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb lb sel'}: </td>
|
||||
<td>
|
||||
<select name='SEL' id='select' style="width: 95px;">
|
||||
END
|
||||
|
||||
foreach (@ALGO) {
|
||||
print "<option value=\"$_\"";
|
||||
if ($_ eq $settings{'SEL'}) {
|
||||
print " selected=\"selected\"";
|
||||
}
|
||||
print ">$_</option>";
|
||||
}
|
||||
|
||||
print <<END;
|
||||
|
||||
</select>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb lb mode'}: </td>
|
||||
<td>
|
||||
<select name='MODE' id='mode' style="width: 95px;">
|
||||
|
||||
END
|
||||
|
||||
foreach (@MODE) {
|
||||
print "<option value=\"$_\"";
|
||||
if ($_ eq $settings{'MODE'}) {
|
||||
print " selected=\"selected\"";
|
||||
}
|
||||
print ">$_</option>";
|
||||
}
|
||||
|
||||
print <<END;
|
||||
|
||||
</select>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb lb endpoints'} <img src='/blob.gif' alt='*' /></td>
|
||||
<td><input type='text' name='ENDPOINTS' value='$settings{'ENDPOINTS'}' size='50'/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb lb eport'} <img src='/blob.gif' alt='*' /></td>
|
||||
<td><input type='text' name='EPORT' value='$settings{'EPORT'}' size='25'/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb lb monitor'}: </td>
|
||||
<td>
|
||||
<select name='MONITOR' id='monitor' style="width: 95px;">
|
||||
|
||||
END
|
||||
|
||||
foreach (@MONITOR) {
|
||||
print "<option value=\"$_\"";
|
||||
if ($_ eq $settings{'MONITOR'}) {
|
||||
print " selected=\"selected\"";
|
||||
}
|
||||
print ">$_</option>";
|
||||
}
|
||||
|
||||
print <<END;
|
||||
|
||||
</select>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td class='base' width='25%'><img src='/blob.gif' align='top' alt='*' /> $Lang::tr{'required field'}</td>
|
||||
<td width='50%' align='right'><input type='hidden' name='ACTION' value='$Lang::tr{'add'}' /><input type='submit' name='SUBMIT' value='$buttontext' /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
END
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'loxilb lb config entries'});
|
||||
print <<END
|
||||
|
||||
<table width='100%' class='tbl'>
|
||||
<tr>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?NAME'><b>$Lang::tr{'loxilb lb name'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?EXTIP'><b>$Lang::tr{'loxilb lb extip'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?PORT'><b>$Lang::tr{'loxilb lb port'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?PROTO'><b>$Lang::tr{'loxilb lb proto'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?SEL'><b>$Lang::tr{'loxilb lb sel'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?MODE'><b>$Lang::tr{'loxilb lb mode'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?ENDPOINTS'><b>$Lang::tr{'loxilb lb endpoints'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?EPORT'><b>$Lang::tr{'loxilb lb eport'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?MONITOR'><b>$Lang::tr{'loxilb lb monitor'}</b></a></th>
|
||||
<th width='10%' colspan='3' class='boldbase' align='center'><b>$Lang::tr{'action'}</b></th>
|
||||
</tr>
|
||||
END
|
||||
;
|
||||
|
||||
#
|
||||
# Print each line of @current list
|
||||
#
|
||||
|
||||
my $key = 0;
|
||||
my $col="";
|
||||
foreach my $line (@current) {
|
||||
chomp($line); # remove newline
|
||||
my @temp=split(/\,/,$line);
|
||||
$temp[2] ='' unless defined $temp[2]; # not always populated
|
||||
$temp[3] ='' unless defined $temp[2]; # not always populated
|
||||
$temp[4] ='' unless defined $temp[3]; # not always populated
|
||||
$temp[5] ='' unless defined $temp[4]; # not always populated
|
||||
$temp[6] ='' unless defined $temp[5]; # not always populated
|
||||
$temp[7] ='' unless defined $temp[6]; # not always populated
|
||||
$temp[8] ='' unless defined $temp[7]; # not always populated
|
||||
$temp[9] ='' unless defined $temp[8]; # not always populated
|
||||
|
||||
#Choose icon for checkbox
|
||||
my $gif = '';
|
||||
my $gdesc = '';
|
||||
if ($temp[0] ne '' ) {
|
||||
$gif = 'on.gif';
|
||||
$gdesc = $Lang::tr{'click to disable'};
|
||||
} else {
|
||||
$gif = 'off.gif';
|
||||
$gdesc = $Lang::tr{'click to enable'};
|
||||
}
|
||||
|
||||
#Colorize each line
|
||||
if ($settings{'KEY1'} eq $key) {
|
||||
print "<tr bgcolor='${Header::colouryellow}'>";
|
||||
} elsif ($key % 2) {
|
||||
print "<tr>";
|
||||
$col="bgcolor='$color{'color20'}'";
|
||||
} else {
|
||||
print "<tr>";
|
||||
$col="bgcolor='$color{'color22'}'";
|
||||
}
|
||||
print <<END
|
||||
<td align='center' $col>$temp[1]</td>
|
||||
<td align='center' $col>$temp[2]</td>
|
||||
<td align='center' $col>$temp[3]</td>
|
||||
<td align='center' $col>$temp[4]</td>
|
||||
<td align='center' $col>$temp[5]</td>
|
||||
<td align='center' $col>$temp[6]</td>
|
||||
<td align='center' $col>$temp[7]</td>
|
||||
<td align='center' $col>$temp[8]</td>
|
||||
<td align='center' $col>$temp[9]</td>
|
||||
<td align='center' $col>
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<input type='hidden' name='ACTION' value='$Lang::tr{'toggle enable disable'}' />
|
||||
<input type='image' name='$Lang::tr{'toggle enable disable'}' src='/images/$gif' alt='$gdesc' title='$gdesc' />
|
||||
<input type='hidden' name='KEY1' value='$key' />
|
||||
</form>
|
||||
</td>
|
||||
|
||||
<td align='center' $col>
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<input type='hidden' name='ACTION' value='$Lang::tr{'edit'}' />
|
||||
<input type='image' name='$Lang::tr{'edit'}' src='/images/edit.gif' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' />
|
||||
<input type='hidden' name='KEY1' value='$key' />
|
||||
</form>
|
||||
</td>
|
||||
|
||||
<td align='center' $col>
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<input type='hidden' name='ACTION' value='$Lang::tr{'remove'}' />
|
||||
<input type='image' name='$Lang::tr{'remove'}' src='/images/delete.gif' alt='$Lang::tr{'remove'}' title='$Lang::tr{'remove'}' />
|
||||
<input type='hidden' name='KEY1' value='$key' />
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
END
|
||||
;
|
||||
$key++;
|
||||
}
|
||||
print "</table>";
|
||||
|
||||
# If table contains entries, print 'Key to action icons'
|
||||
if ($key) {
|
||||
print <<END
|
||||
<table>
|
||||
<tr>
|
||||
<td class='boldbase'> <b>$Lang::tr{'legend'}: </b></td>
|
||||
<td><img src='/images/on.gif' alt='$Lang::tr{'click to disable'}' /></td>
|
||||
<td class='base'>$Lang::tr{'click to disable'}</td>
|
||||
<td> </td>
|
||||
<td><img src='/images/off.gif' alt='$Lang::tr{'click to enable'}' /></td>
|
||||
<td class='base'>$Lang::tr{'click to enable'}</td>
|
||||
<td> </td>
|
||||
<td><img src='/images/edit.gif' alt='$Lang::tr{'edit'}' /></td>
|
||||
<td class='base'>$Lang::tr{'edit'}</td>
|
||||
<td> </td>
|
||||
<td><img src='/images/delete.gif' alt='$Lang::tr{'remove'}' /></td>
|
||||
<td class='base'>$Lang::tr{'remove'}</td>
|
||||
</tr>
|
||||
</table>
|
||||
END
|
||||
;
|
||||
}
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::closebigbox();
|
||||
&Header::closepage();
|
||||
|
||||
## Ouf it's the end !
|
||||
|
||||
# Sort the "current" array according to choices
|
||||
sub SortDataFile
|
||||
{
|
||||
our %entries = ();
|
||||
|
||||
# Sort pair of record received in $a $b special vars.
|
||||
# When IP is specified use numeric sort else alpha.
|
||||
# If sortname ends with 'Rev', do reverse sort.
|
||||
#
|
||||
sub fixedleasesort {
|
||||
my $qs=''; # The sort field specified minus 'Rev'
|
||||
if (rindex ($settings{'SORT_NAMELIST'},'Rev') != -1) {
|
||||
$qs=substr ($settings{'SORT_NAMELIST'},0,length($settings{'SORT_NAMELIST'})-3);
|
||||
if ($qs eq 'NAME') {
|
||||
my @a = split(/\./,$entries{$a}->{$qs});
|
||||
my @b = split(/\./,$entries{$b}->{$qs});
|
||||
($b[0]<=>$a[0]) ||
|
||||
($b[1]<=>$a[1]) ||
|
||||
($b[2]<=>$a[2]) ||
|
||||
($b[3]<=>$a[3]);
|
||||
} else {
|
||||
$entries{$b}->{$qs} cmp $entries{$a}->{$qs};
|
||||
}
|
||||
} else { #not reverse
|
||||
$qs=$settings{'SORT_NAMELIST'};
|
||||
if ($qs eq 'NAME') {
|
||||
my @a = split(/\./,$entries{$a}->{$qs});
|
||||
my @b = split(/\./,$entries{$b}->{$qs});
|
||||
($a[0]<=>$b[0]) ||
|
||||
($a[1]<=>$b[1]) ||
|
||||
($a[2]<=>$b[2]) ||
|
||||
($a[3]<=>$b[3]);
|
||||
} else {
|
||||
$entries{$a}->{$qs} cmp $entries{$b}->{$qs};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Use an associative array (%entries)
|
||||
my $key = 0;
|
||||
foreach my $line (@current) {
|
||||
chomp( $line); #remove newline because can be on field 5 or 6 (addition of REMARK)
|
||||
my @temp = ( '','','', '');
|
||||
@temp = split (',',$line);
|
||||
|
||||
# Build a pair 'Field Name',value for each of the data dataline.
|
||||
# Each SORTABLE field must have is pair.
|
||||
# Other data fields (non sortable) can be grouped in one
|
||||
|
||||
my @record = ('KEY',$key++,'EN',$temp[0],'NAME',$temp[1],'EXTIP',$temp[2],'PORT',$temp[3],'PROTO',$temp[4],'SEL',$temp[5],'MODE',$temp[6],'ENDPOINTS',$temp[7],'EPORT',$temp[8],'MONITOR',$temp[9]);
|
||||
my $record = {}; # create a reference to empty hash
|
||||
%{$record} = @record; # populate that hash with @record
|
||||
$entries{$record->{KEY}} = $record; # add this to a hash of hashes
|
||||
}
|
||||
|
||||
open(FILE, ">$datafile") or die 'routing datafile error';
|
||||
|
||||
# Each field value is printed , with the newline ! Don't forget separator and order of them.
|
||||
foreach my $entry (sort fixedleasesort keys %entries) {
|
||||
print FILE "$entries{$entry}->{EN},$entries{$entry}->{NAME},$entries{$entry}->{EXTIP},$entries{$entry}->{PORT},$entries{$entry}->{PROTO},$entries{$entry}->{SEL},$entries{$entry}->{MODE},$entries{$entry}->{ENDPOINTS},$entries{$entry}->{EPORT},$entries{$entry}->{MONITOR}\n";
|
||||
}
|
||||
|
||||
close(FILE);
|
||||
# Reload sorted @current
|
||||
open (FILE, "$datafile");
|
||||
@current = <FILE>;
|
||||
close (FILE);
|
||||
}
|
||||
|
||||
sub SaveLB {
|
||||
my @save_options;
|
||||
my $command = 'loxicmd';
|
||||
my $dir="/var/ipfire/loxilb/";
|
||||
push(@save_options, "save", "--lb", "-c", $dir);
|
||||
&General::system_output($command, @save_options);
|
||||
#my @output = &General::system_output($command, @save_options);
|
||||
#$errormessage = join('', @output);
|
||||
}
|
||||
|
||||
#
|
||||
# Build the configuration file
|
||||
#
|
||||
sub CreateLB {
|
||||
my (%settings) = @_;
|
||||
my $sel;
|
||||
my $mode;
|
||||
my @loxicmd_options;
|
||||
my $command = 'loxicmd';
|
||||
my $name = "--name=" . "$settings{'NAME'}";
|
||||
my $proto = "--" . "$settings{'PROTO'}" . "=" . "$settings{'PORT'}" . ":" . "$settings{'EPORT'}";
|
||||
|
||||
if ($settings{'SEL'}) {
|
||||
$sel = "--select=" . "$settings{'SEL'}";
|
||||
}
|
||||
if ($settings{'MODE'}) {
|
||||
$mode = "--mode=" . "$settings{'MODE'}";
|
||||
}
|
||||
my $tmp = $settings{'ENDPOINTS'};
|
||||
$tmp =~ s/\|/,/g;
|
||||
my $endpoints = "--endpoints=$tmp";
|
||||
push(@loxicmd_options, "create", "lb");
|
||||
push(@loxicmd_options, "$settings{'EXTIP'}");
|
||||
push(@loxicmd_options, "$name");
|
||||
push(@loxicmd_options, "$proto");
|
||||
if ($sel) {
|
||||
push(@loxicmd_options, "$sel");
|
||||
}
|
||||
if ($mode) {
|
||||
push(@loxicmd_options, "$mode");
|
||||
}
|
||||
push(@loxicmd_options, "$endpoints");
|
||||
if ($settings{'MONITOR'} eq 'on') {
|
||||
push(@loxicmd_options, "--monitor");
|
||||
}
|
||||
&General::system($command, @loxicmd_options);
|
||||
&SaveLB;
|
||||
}
|
||||
|
||||
sub DeleteLB {
|
||||
my (%settings) = @_;
|
||||
my @loxicmd_options;
|
||||
my $command = 'loxicmd';
|
||||
my $name = "--name=" . "$settings{'NAME'}";
|
||||
push(@loxicmd_options, "delete", "lb");
|
||||
push(@loxicmd_options, "$name");
|
||||
&General::system($command, @loxicmd_options);
|
||||
&SaveLB;
|
||||
}
|
||||
653
html/cgi-bin/loxilbfw.cgi
Normal file
653
html/cgi-bin/loxilbfw.cgi
Normal file
@@ -0,0 +1,653 @@
|
||||
#!/usr/bin/perl
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2011 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2024 BPFire Team #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
use strict;
|
||||
|
||||
# enable only the following on debugging purpose
|
||||
use warnings;
|
||||
#use CGI::Carp 'fatalsToBrowser';
|
||||
|
||||
require '/var/ipfire/general-functions.pl';
|
||||
require "${General::swroot}/lang.pl";
|
||||
require "${General::swroot}/header.pl";
|
||||
|
||||
#workaround to suppress a warning when a variable is used only once
|
||||
my @dummy = ( ${Header::colouryellow} );
|
||||
undef (@dummy);
|
||||
|
||||
# Files used
|
||||
my $setting = "${General::swroot}/main/settings";
|
||||
our $datafile = "${General::swroot}/loxilb/fwconfig"; #(our: used in subroutine)
|
||||
|
||||
my %color = ();
|
||||
my %mainsettings = ();
|
||||
&General::readhash("${General::swroot}/main/settings", \%mainsettings);
|
||||
&General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", \%color);
|
||||
|
||||
our %settings = ();
|
||||
|
||||
$settings{'EN'} = ''; # reuse for dummy field in position zero
|
||||
$settings{'sourceIP'} = '';
|
||||
$settings{'destinationIP'} = '';
|
||||
$settings{'minSourcePort'} = '';
|
||||
$settings{'maxSourcePort'} = '';
|
||||
$settings{'minDestinationPort'} = '';
|
||||
$settings{'maxDestinationPort'} = '';
|
||||
$settings{'protocol'} = '';
|
||||
$settings{'portName'} = '';
|
||||
$settings{'preference'} = '';
|
||||
$settings{'ruleAction'} = '';
|
||||
my @nosaved=('EN','sourceIP','destinationIP','minSourcePort','maxSourcePort','minDestinationPort','maxDestinationPort','protocol','portName','preference','ruleAction'); # List here ALL setting2 fields. Mandatory
|
||||
|
||||
$settings{'ACTION'} = ''; # add/edit/remove
|
||||
$settings{'KEY1'} = ''; # point record for ACTION
|
||||
|
||||
#Define each field that can be used to sort columns
|
||||
my $sortstring='^sourceIP';
|
||||
$settings{'SORT_sourceIPLIST'} = 'sourceIP';
|
||||
my $errormessage = '';
|
||||
my $warnmessage = '';
|
||||
|
||||
&Header::showhttpheaders();
|
||||
|
||||
#Get GUI values
|
||||
&Header::getcgihash(\%settings);
|
||||
|
||||
###############
|
||||
# DEBUG DEBUG
|
||||
#&Header::openbox('100%', 'left', 'DEBUG');
|
||||
#my $debugCount = 0;
|
||||
#foreach my $line (sort keys %settings) {
|
||||
#print "$line = $settings{$line}<br />\n";
|
||||
# $debugCount++;
|
||||
#}
|
||||
#print " Count: $debugCount\n";
|
||||
#&Header::closebox();
|
||||
# DEBUG DEBUG
|
||||
###############
|
||||
|
||||
# Load multiline data
|
||||
our @current = ();
|
||||
if (open(FILE, "$datafile")) {
|
||||
@current = <FILE>;
|
||||
close (FILE);
|
||||
}
|
||||
|
||||
## Settings1 Box not used...
|
||||
&General::readhash("${General::swroot}/main/settings", \%settings);
|
||||
|
||||
|
||||
## Now manipulate the multi-line list with Settings2
|
||||
# Basic actions are:
|
||||
# toggle the check box
|
||||
# add/update a new line
|
||||
# begin editing a line
|
||||
# remove a line
|
||||
|
||||
|
||||
# Toggle enable/disable field. Field is in second position
|
||||
if ($settings{'ACTION'} eq $Lang::tr{'toggle enable disable'}) {
|
||||
#move out new line
|
||||
chomp(@current[$settings{'KEY1'}]);
|
||||
my @temp = split(/\,/,@current[$settings{'KEY1'}]);
|
||||
|
||||
$temp[0] = $temp[0] ne '' ? '' : 'on'; # Toggle the field
|
||||
@current[$settings{'KEY1'}] = join (',',@temp)."\n";
|
||||
$settings{'KEY1'} = ''; # End edit mode
|
||||
|
||||
&General::log($Lang::tr{'loxilb fw changed'});
|
||||
|
||||
#Save current
|
||||
open(FILE, ">$datafile") or die 'loxilb fw datafile error';
|
||||
print FILE @current;
|
||||
close(FILE);
|
||||
|
||||
# Rebuild configuration file
|
||||
#&BuildConfiguration;
|
||||
}
|
||||
|
||||
if ($settings{'ACTION'} eq $Lang::tr{'add'}) {
|
||||
# Validate inputs
|
||||
if (!&General::validipandmask($settings{'sourceIP'})){
|
||||
$errormessage = $Lang::tr{'invalid ip'}." / ".$Lang::tr{'invalid netmask'};
|
||||
}else{
|
||||
#set networkip if not already correctly defined
|
||||
my($ip,$cidr) = split(/\//,$settings{'sourceIP'});
|
||||
$cidr = &General::iporsubtocidr($cidr);
|
||||
my $netip=&General::getnetworkip($ip,$cidr);
|
||||
$settings{'sourceIP'} = "$netip/$cidr";
|
||||
}
|
||||
|
||||
if (!&General::validipandmask($settings{'destinationIP'})){
|
||||
$errormessage = $Lang::tr{'invalid ip'}." / ".$Lang::tr{'invalid netmask'};
|
||||
}else{
|
||||
#set networkip if not already correctly defined
|
||||
my($ip,$cidr) = split(/\//,$settings{'destinationIP'});
|
||||
$cidr = &General::iporsubtocidr($cidr);
|
||||
my $netip=&General::getnetworkip($ip,$cidr);
|
||||
$settings{'destinationIP'} = "$netip/$cidr";
|
||||
}
|
||||
|
||||
#Check for already existing routing entry
|
||||
foreach my $line (@current) {
|
||||
chomp($line); # remove newline
|
||||
my @temp=split(/\,/,$line);
|
||||
$temp[2] ='' unless defined $temp[2]; # destinationIP
|
||||
$temp[3] ='' unless defined $temp[2]; # minSourcePort
|
||||
$temp[4] ='' unless defined $temp[3]; # maxSourcePort
|
||||
$temp[5] ='' unless defined $temp[4]; # minDestinationPort
|
||||
$temp[6] ='' unless defined $temp[5]; # maxDestinationPort
|
||||
$temp[7] ='' unless defined $temp[6]; # protocol
|
||||
$temp[8] ='' unless defined $temp[7]; # portName
|
||||
$temp[9] ='' unless defined $temp[8]; # preference
|
||||
$temp[10] ='' unless defined $temp[9]; # ruleAction
|
||||
#Same ip already used?
|
||||
if($temp[1] eq $settings{'sourceIP'} && $settings{'KEY1'} eq ''){
|
||||
$errormessage = $Lang::tr{'ccd err loxilbconfigeexist'};
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
unless ($errormessage) {
|
||||
if ($settings{'KEY1'} eq '') { #add or edit ?
|
||||
unshift (@current, "$settings{'EN'},$settings{'sourceIP'},$settings{'destinationIP'},$settings{'minSourcePort'},$settings{'maxSourcePort'},$settings{'minDestinationPort'},$settings{'maxDestinationPort'},$settings{'protocol'},$settings{'portName'},$settings{'preference'},$settings{'ruleAction'}\n");
|
||||
&General::log($Lang::tr{'loxilb lb config added'});
|
||||
} else {
|
||||
@current[$settings{'KEY1'}] = "$settings{'EN'},$settings{'sourceIP'},$settings{'destinationIP'},$settings{'minSourcePort'},$settings{'maxSourcePort'},$settings{'minDestinationPort'},$settings{'maxDestinationPort'},$settings{'protocol'},$settings{'portName'},$settings{'preference'},$settings{'ruleAction'}\n";
|
||||
$settings{'KEY1'} = ''; # End edit mode
|
||||
&General::log($Lang::tr{'loxilb fw changed'});
|
||||
}
|
||||
|
||||
if ($settings{'EN'} eq 'on') {
|
||||
&DeleteFW(%settings);
|
||||
&CreateFW(%settings);
|
||||
}
|
||||
|
||||
# Write changes to config file.
|
||||
&SortDataFile; # sort newly added/modified entry
|
||||
|
||||
#map ($settings{$_}='' ,@nosaved); # Clear fields
|
||||
}
|
||||
}
|
||||
|
||||
if ($settings{'ACTION'} eq $Lang::tr{'edit'}) {
|
||||
#move out new line
|
||||
my $line = @current[$settings{'KEY1'}]; # KEY1 is the index in current
|
||||
chomp($line);
|
||||
my @temp = split(/\,/, $line);
|
||||
$settings{'EN'}=$temp[0]; # Prepare the screen for editing
|
||||
$settings{'sourceIP'}=$temp[1];
|
||||
$settings{'destinationIP'}=$temp[2];
|
||||
$settings{'minSourcePort'}=$temp[3];
|
||||
$settings{'maxSourcePort'}=$temp[4];
|
||||
$settings{'minDestinationPort'}=$temp[5];
|
||||
$settings{'maxDestinationPort'}=$temp[6];
|
||||
$settings{'protocol'}=$temp[7];
|
||||
$settings{'portName'}=$temp[8];
|
||||
$settings{'preference'}=$temp[9];
|
||||
$settings{'ruleAction'}=$temp[10];
|
||||
if ($settings{'EN'} eq 'on') {
|
||||
&CreateFW(%settings);
|
||||
}
|
||||
}
|
||||
|
||||
if ($settings{'ACTION'} eq $Lang::tr{'remove'}) {
|
||||
|
||||
my $line = @current[$settings{'KEY1'}]; # KEY1 is the index in current
|
||||
chomp($line);
|
||||
my @temp = split(/\,/, $line);
|
||||
$settings{'EN'}=$temp[0]; # Prepare the screen for editing
|
||||
$settings{'sourceIP'}=$temp[1];
|
||||
$settings{'destinationIP'}=$temp[2];
|
||||
$settings{'minSourcePort'}=$temp[3];
|
||||
$settings{'maxSourcePort'}=$temp[4];
|
||||
$settings{'minDestinationPort'}=$temp[5];
|
||||
$settings{'maxDestinationPort'}=$temp[6];
|
||||
$settings{'protocol'}=$temp[7];
|
||||
$settings{'portName'}=$temp[8];
|
||||
$settings{'preference'}=$temp[9];
|
||||
$settings{'ruleAction'}=$temp[10];
|
||||
|
||||
&DeleteFW(%settings);
|
||||
|
||||
splice (@current,$settings{'KEY1'},1); # Delete line
|
||||
open(FILE, ">$datafile") or die 'route datafile error';
|
||||
print FILE @current;
|
||||
close(FILE);
|
||||
$settings{'KEY1'} = ''; # End remove mode
|
||||
&General::log($Lang::tr{'loxilb fw changed'});
|
||||
|
||||
#&BuildConfiguration; # then re-build conf which use new data
|
||||
}
|
||||
|
||||
## Check if sorting is asked
|
||||
# If same column clicked, reverse the sort.
|
||||
if ($ENV{'QUERY_STRING'} =~ /$sortstring/ ) {
|
||||
my $newsort=$ENV{'QUERY_STRING'};
|
||||
my $actual=$settings{'SORT_sourceIPLIST'};
|
||||
#Reverse actual sort ?
|
||||
if ($actual =~ $newsort) {
|
||||
my $Rev='';
|
||||
if ($actual !~ 'Rev') {
|
||||
$Rev='Rev';
|
||||
}
|
||||
$newsort.=$Rev;
|
||||
}
|
||||
$settings{'SORT_sourceIPLIST'}=$newsort;
|
||||
map (delete ($settings{$_}) ,(@nosaved,'ACTION','KEY1'));# Must never be saved
|
||||
&General::writehash($setting, \%settings);
|
||||
&SortDataFile;
|
||||
$settings{'ACTION'} = 'SORT'; # Create an 'ACTION'
|
||||
map ($settings{$_} = '' ,@nosaved,'KEY1'); # and reinit vars to empty
|
||||
}
|
||||
|
||||
if ($settings{'ACTION'} eq '' ) { # First launch from GUI
|
||||
# Place here default value when nothing is initialized
|
||||
$settings{'EN'} = 'on';
|
||||
$settings{'sourceIP'} = '';
|
||||
$settings{'destinationIP'} = '';
|
||||
$settings{'minSourcePort'} = '';
|
||||
$settings{'maxSourcePort'} = '';
|
||||
$settings{'minDestinationPort'} = '';
|
||||
$settings{'maxDestinationPort'} = '';
|
||||
$settings{'protocol'} = '';
|
||||
$settings{'portName'} = '';
|
||||
$settings{'preference'} = '';
|
||||
$settings{'ruleAction'} = '';
|
||||
}
|
||||
|
||||
&Header::openpage($Lang::tr{'loxilb fw entries'}, 1, '');
|
||||
&Header::openbigbox('100%', 'left', '', $errormessage);
|
||||
my %checked=(); # Checkbox manipulations
|
||||
|
||||
if ($errormessage) {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'error messages'});
|
||||
print "<font class='base' color=red>$errormessage </font>";
|
||||
&Header::closebox();
|
||||
}
|
||||
|
||||
#
|
||||
|
||||
$checked{'EN'}{'on'} = ($settings{'EN'} eq '' ) ? '' : "checked='checked'";
|
||||
|
||||
my $buttontext = $Lang::tr{'add'};
|
||||
if ($settings{'KEY1'} ne '') {
|
||||
$buttontext = $Lang::tr{'update'};
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'loxilb fw edit'});
|
||||
} else {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'loxilb fw add'});
|
||||
}
|
||||
|
||||
my @PROTOCOLS = ("any", "tcp", "udp", "icmp");
|
||||
my @RULEACTIONS = ("allow", "drop");
|
||||
|
||||
#Edited line number (KEY1) passed until cleared by 'save' or 'remove' or 'new sort order'
|
||||
print <<END;
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<input type='hidden' name='KEY1' value='$settings{'KEY1'}' />
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb fw sourceIP'} <img src='/blob.gif' alt='*' /></td>
|
||||
<td><input type='text' name='sourceIP' value='$settings{'sourceIP'}' size='25'/></td>
|
||||
</tr><tr>
|
||||
<td class='base'>$Lang::tr{'loxilb fw destinationIP'} <img src='/blob.gif' alt='*' /></td>
|
||||
<td><input type='text' name='destinationIP' value='$settings{'destinationIP'}' size='25'/></td>
|
||||
<td class='base'>$Lang::tr{'enabled'}</td>
|
||||
<td><input type='checkbox' name='EN' $checked{'EN'}{'on'} /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb fw minSourcePort'}: </td>
|
||||
<td><input type='text' name='minSourcePort' value='$settings{'minSourcePort'}' size='25'/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb fw maxSourcePort'}: </td>
|
||||
<td><input type='text' name='maxSourcePort' value='$settings{'maxSourcePort'}' size='25'/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb fw minDestinationPort'}: </td>
|
||||
<td><input type='text' name='minDestinationPort' value='$settings{'minDestinationPort'}' size='25'/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb fw maxDestinationPort'}: </td>
|
||||
<td><input type='text' name='maxDestinationPort' value='$settings{'maxDestinationPort'}' size='25'/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb fw proto'}: </td>
|
||||
<td>
|
||||
<select name='protocol' id='protocol' style="width: 95px;">
|
||||
END
|
||||
|
||||
# Insert the dynamic options for the 'PROTO' select element
|
||||
foreach (@PROTOCOLS) {
|
||||
print "<option value=\"$_\"";
|
||||
if ($_ eq $settings{'protocol'}) {
|
||||
print " selected=\"selected\"";
|
||||
}
|
||||
print ">$_</option>";
|
||||
}
|
||||
|
||||
print <<END;
|
||||
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb fw portName'}: </td>
|
||||
<td><input type='text' name='portName' value='$settings{'portName'}' size='25'/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb fw preference'}: </td>
|
||||
<td><input type='text' name='preference' value='$settings{'preference'}' size='25'/></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb fw action'}: </td>
|
||||
<td>
|
||||
<select name='ruleAction' id='ruleAction' style="width: 95px;">
|
||||
END
|
||||
|
||||
# Insert the dynamic options for the 'PROTO' select element
|
||||
foreach (@RULEACTIONS) {
|
||||
print "<option value=\"$_\"";
|
||||
if ($_ eq $settings{'ruleAction'}) {
|
||||
print " selected=\"selected\"";
|
||||
}
|
||||
print ">$_</option>";
|
||||
}
|
||||
|
||||
print <<END;
|
||||
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
<br>
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td class='base' width='25%'><img src='/blob.gif' align='top' alt='*' /> $Lang::tr{'required field'}</td>
|
||||
<td width='50%' align='right'><input type='hidden' name='ACTION' value='$Lang::tr{'add'}' /><input type='submit' name='SUBMIT' value='$buttontext' /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
END
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'loxilb fw entries'});
|
||||
print <<END
|
||||
|
||||
<table width='100%' class='tbl'>
|
||||
<tr>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?sourceIP'><b>$Lang::tr{'loxilb fw sourceIP'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?destinationIP'><b>$Lang::tr{'loxilb fw destinationIP'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?minSourcePort'><b>$Lang::tr{'loxilb fw minSourcePort'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?maxSourcePort'><b>$Lang::tr{'loxilb fw maxSourcePort'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?minDestinationPort'><b>$Lang::tr{'loxilb fw minDestinationPort'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?maxDestinationPort'><b>$Lang::tr{'loxilb fw maxDestinationPort'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?protocol'><b>$Lang::tr{'loxilb fw proto'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?portName'><b>$Lang::tr{'loxilb fw portName'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?preference'><b>$Lang::tr{'loxilb fw preference'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?ruleAction'><b>$Lang::tr{'loxilb fw action'}</b></a></th>
|
||||
<th width='10%' colspan='3' class='boldbase' align='center'><b>$Lang::tr{'action'}</b></th>
|
||||
</tr>
|
||||
END
|
||||
;
|
||||
|
||||
#
|
||||
# Print each line of @current list
|
||||
#
|
||||
|
||||
my $key = 0;
|
||||
my $col="";
|
||||
foreach my $line (@current) {
|
||||
chomp($line); # remove newline
|
||||
my @temp=split(/\,/,$line);
|
||||
$temp[2] ='' unless defined $temp[2]; # not always populated
|
||||
$temp[3] ='' unless defined $temp[2]; # not always populated
|
||||
$temp[4] ='' unless defined $temp[3]; # not always populated
|
||||
$temp[5] ='' unless defined $temp[4]; # not always populated
|
||||
$temp[6] ='' unless defined $temp[5]; # not always populated
|
||||
$temp[7] ='' unless defined $temp[6]; # not always populated
|
||||
$temp[8] ='' unless defined $temp[7]; # not always populated
|
||||
$temp[9] ='' unless defined $temp[8]; # not always populated
|
||||
$temp[10] ='' unless defined $temp[9]; # not always populated
|
||||
|
||||
#Choose icon for checkbox
|
||||
my $gif = '';
|
||||
my $gdesc = '';
|
||||
if ($temp[0] ne '' ) {
|
||||
$gif = 'on.gif';
|
||||
$gdesc = $Lang::tr{'click to disable'};
|
||||
} else {
|
||||
$gif = 'off.gif';
|
||||
$gdesc = $Lang::tr{'click to enable'};
|
||||
}
|
||||
|
||||
#Colorize each line
|
||||
if ($settings{'KEY1'} eq $key) {
|
||||
print "<tr bgcolor='${Header::colouryellow}'>";
|
||||
} elsif ($key % 2) {
|
||||
print "<tr>";
|
||||
$col="bgcolor='$color{'color20'}'";
|
||||
} else {
|
||||
print "<tr>";
|
||||
$col="bgcolor='$color{'color22'}'";
|
||||
}
|
||||
print <<END
|
||||
<td align='center' $col>$temp[1]</td>
|
||||
<td align='center' $col>$temp[2]</td>
|
||||
<td align='center' $col>$temp[3]</td>
|
||||
<td align='center' $col>$temp[4]</td>
|
||||
<td align='center' $col>$temp[5]</td>
|
||||
<td align='center' $col>$temp[6]</td>
|
||||
<td align='center' $col>$temp[7]</td>
|
||||
<td align='center' $col>$temp[8]</td>
|
||||
<td align='center' $col>$temp[9]</td>
|
||||
<td align='center' $col>$temp[10]</td>
|
||||
<td align='center' $col>
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<input type='hidden' name='ACTION' value='$Lang::tr{'toggle enable disable'}' />
|
||||
<input type='image' name='$Lang::tr{'toggle enable disable'}' src='/images/$gif' alt='$gdesc' title='$gdesc' />
|
||||
<input type='hidden' name='KEY1' value='$key' />
|
||||
</form>
|
||||
</td>
|
||||
|
||||
<td align='center' $col>
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<input type='hidden' name='ACTION' value='$Lang::tr{'remove'}' />
|
||||
<input type='image' name='$Lang::tr{'remove'}' src='/images/delete.gif' alt='$Lang::tr{'remove'}' title='$Lang::tr{'remove'}' />
|
||||
<input type='hidden' name='KEY1' value='$key' />
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
END
|
||||
;
|
||||
$key++;
|
||||
}
|
||||
print "</table>";
|
||||
|
||||
# If table contains entries, print 'Key to action icons'
|
||||
if ($key) {
|
||||
print <<END
|
||||
<table>
|
||||
<tr>
|
||||
<td class='boldbase'> <b>$Lang::tr{'legend'}: </b></td>
|
||||
<td><img src='/images/on.gif' alt='$Lang::tr{'click to disable'}' /></td>
|
||||
<td class='base'>$Lang::tr{'click to disable'}</td>
|
||||
<td> </td>
|
||||
<td><img src='/images/off.gif' alt='$Lang::tr{'click to enable'}' /></td>
|
||||
<td class='base'>$Lang::tr{'click to enable'}</td>
|
||||
<td> </td>
|
||||
<td><img src='/images/delete.gif' alt='$Lang::tr{'remove'}' /></td>
|
||||
<td class='base'>$Lang::tr{'remove'}</td>
|
||||
</tr>
|
||||
</table>
|
||||
END
|
||||
;
|
||||
}
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::closebigbox();
|
||||
&Header::closepage();
|
||||
|
||||
## Ouf it's the end !
|
||||
|
||||
# Sort the "current" array according to choices
|
||||
sub SortDataFile
|
||||
{
|
||||
our %entries = ();
|
||||
|
||||
# Sort pair of record received in $a $b special vars.
|
||||
# When IP is specified use numeric sort else alpha.
|
||||
# If sortname ends with 'Rev', do reverse sort.
|
||||
#
|
||||
sub fixedleasesort {
|
||||
my $qs=''; # The sort field specified minus 'Rev'
|
||||
if (rindex ($settings{'SORT_sourceIPLIST'},'Rev') != -1) {
|
||||
$qs=substr ($settings{'SORT_sourceIPLIST'},0,length($settings{'SORT_sourceIPLIST'})-3);
|
||||
if ($qs eq 'sourceIP') {
|
||||
my @a = split(/\./,$entries{$a}->{$qs});
|
||||
my @b = split(/\./,$entries{$b}->{$qs});
|
||||
($b[0]<=>$a[0]) ||
|
||||
($b[1]<=>$a[1]) ||
|
||||
($b[2]<=>$a[2]) ||
|
||||
($b[3]<=>$a[3]);
|
||||
} else {
|
||||
$entries{$b}->{$qs} cmp $entries{$a}->{$qs};
|
||||
}
|
||||
} else { #not reverse
|
||||
$qs=$settings{'SORT_sourceIPLIST'};
|
||||
if ($qs eq 'sourceIP') {
|
||||
my @a = split(/\./,$entries{$a}->{$qs});
|
||||
my @b = split(/\./,$entries{$b}->{$qs});
|
||||
($a[0]<=>$b[0]) ||
|
||||
($a[1]<=>$b[1]) ||
|
||||
($a[2]<=>$b[2]) ||
|
||||
($a[3]<=>$b[3]);
|
||||
} else {
|
||||
$entries{$a}->{$qs} cmp $entries{$b}->{$qs};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Use an associative array (%entries)
|
||||
my $key = 0;
|
||||
foreach my $line (@current) {
|
||||
chomp( $line); #remove newline because can be on field 5 or 6 (addition of REMARK)
|
||||
my @temp = ( '','','', '');
|
||||
@temp = split (',',$line);
|
||||
|
||||
# Build a pair 'Field Name',value for each of the data dataline.
|
||||
# Each SORTABLE field must have is pair.
|
||||
# Other data fields (non sortable) can be grouped in one
|
||||
|
||||
my @record = ('KEY',$key++,'EN',$temp[0],'sourceIP',$temp[1],'destinationIP',$temp[2],'minSourcePort',$temp[3],'maxSourcePort',$temp[4],'minDestinationPort',$temp[5],'maxDestinationPort',$temp[6],'protocol',$temp[7],'portName',$temp[8],'preference',$temp[9],'ruleAction',$temp[10]);
|
||||
my $record = {}; # create a reference to empty hash
|
||||
%{$record} = @record; # populate that hash with @record
|
||||
$entries{$record->{KEY}} = $record; # add this to a hash of hashes
|
||||
}
|
||||
|
||||
open(FILE, ">$datafile") or die 'routing datafile error';
|
||||
|
||||
# Each field value is printed , with the newline ! Don't forget separator and order of them.
|
||||
foreach my $entry (sort fixedleasesort keys %entries) {
|
||||
print FILE "$entries{$entry}->{EN},$entries{$entry}->{sourceIP},$entries{$entry}->{destinationIP},$entries{$entry}->{minSourcePort},$entries{$entry}->{maxSourcePort},$entries{$entry}->{minDestinationPort},$entries{$entry}->{maxDestinationPort},$entries{$entry}->{protocol},$entries{$entry}->{portName},$entries{$entry}->{preference},$entries{$entry}->{ruleAction}\n";
|
||||
}
|
||||
|
||||
close(FILE);
|
||||
# Reload sorted @current
|
||||
open (FILE, "$datafile");
|
||||
@current = <FILE>;
|
||||
close (FILE);
|
||||
}
|
||||
|
||||
sub manageFW {
|
||||
my ($action, %settings) = @_;
|
||||
|
||||
# Initialize variables
|
||||
my @loxicmd_options;
|
||||
my $command = 'loxicmd';
|
||||
my $firewallRule = "--firewallRule="; # Start quote
|
||||
|
||||
# Construct firewall rule
|
||||
$firewallRule .= "sourceIP:$settings{'sourceIP'},destinationIP:$settings{'destinationIP'}";
|
||||
$firewallRule .= ",minSourcePort:$settings{'minSourcePort'}" if $settings{'minSourcePort'};
|
||||
$firewallRule .= ",maxSourcePort:$settings{'maxSourcePort'}" if $settings{'maxSourcePort'};
|
||||
$firewallRule .= ",minDestinationPort:$settings{'minDestinationPort'}" if $settings{'minDestinationPort'};
|
||||
$firewallRule .= ",maxDestinationPort:$settings{'maxDestinationPort'}" if $settings{'maxDestinationPort'};
|
||||
$firewallRule .= ",portName:$settings{'portName'}" if $settings{'portName'};
|
||||
|
||||
if ($settings{'protocol'} eq "any") {
|
||||
$firewallRule .= ",protocol:0";
|
||||
} elsif ($settings{'protocol'} eq "tcp") {
|
||||
$firewallRule .= ",protocol:6";
|
||||
} elsif ($settings{'protocol'} eq "udp") {
|
||||
$firewallRule .= ",protocol:17";
|
||||
} elsif ($settings{'protocol'} eq "icmp") {
|
||||
$firewallRule .= ",protocol:1";
|
||||
}
|
||||
|
||||
$firewallRule .= ",preference:$settings{'preference'}" if $settings{'preference'};
|
||||
|
||||
my $ruleAction = "--$settings{'ruleAction'}";
|
||||
|
||||
# Push options for loxicmd
|
||||
if ($action eq "create") {
|
||||
push(@loxicmd_options, $action, "firewall", $firewallRule, $ruleAction);
|
||||
} else {
|
||||
push(@loxicmd_options, $action, "firewall", $firewallRule);
|
||||
}
|
||||
|
||||
# Execute the command
|
||||
my $result = &General::system($command, @loxicmd_options);
|
||||
|
||||
# Check for errors
|
||||
if ($result != 0) {
|
||||
print "Error: Failed to execute loxicmd command.\n";
|
||||
# You might want to add more detailed error handling here
|
||||
}
|
||||
}
|
||||
|
||||
sub SaveFW {
|
||||
my @save_options;
|
||||
my $command = 'loxicmd';
|
||||
my $dir="/var/ipfire/loxilb/";
|
||||
push(@save_options, "save", "--firewall", "-c", $dir);
|
||||
&General::system_output($command, @save_options);
|
||||
#my @output = &General::system_output($command, @save_options);
|
||||
#$errormessage = join('', @output);
|
||||
}
|
||||
|
||||
sub CreateFW {
|
||||
my (%settings) = @_;
|
||||
manageFW("create", %settings);
|
||||
&SaveFW;
|
||||
}
|
||||
|
||||
sub DeleteFW {
|
||||
my (%settings) = @_;
|
||||
manageFW("delete", %settings);
|
||||
&SaveFW;
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2020 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2007-2025 IPFire Team <info@ipfire.org> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
@@ -218,11 +218,13 @@ END
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$Lang::tr{'email mailuser'}</td>
|
||||
<td><input type='text' name='txt_mailuser' value='$auth{'AUTHNAME'}' style='width:22em;'></td>
|
||||
<td><input type='text' name='txt_mailuser'
|
||||
value='@{[ &Header::escape($auth{'AUTHNAME'}) ]}' style='width:22em;'></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$Lang::tr{'email mailpass'}</td>
|
||||
<td><input type='password' name='txt_mailpass' value='$auth{'AUTHPASS'}' style='width:22em;' ></td>
|
||||
<td><input type='password' name='txt_mailpass'
|
||||
value='@{[ &Header::escape($auth{'AUTHPASS'}) ]}' style='width:22em;' ></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$Lang::tr{'email tls'}</td>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2021 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2007-2025 IPFire Team <info@ipfire.org> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
@@ -20,7 +20,6 @@
|
||||
###############################################################################
|
||||
|
||||
use strict;
|
||||
use Apache::Htpasswd;
|
||||
use Scalar::Util qw(looks_like_number);
|
||||
|
||||
# enable only the following on debugging purpose
|
||||
@@ -956,7 +955,8 @@ if ($netsettings{'BLUE_DEV'}) {
|
||||
}
|
||||
print <<END
|
||||
<td class='base'>$Lang::tr{'advproxy visible hostname'}:</td>
|
||||
<td><input type='text' name='VISIBLE_HOSTNAME' value='$proxysettings{'VISIBLE_HOSTNAME'}' /></td>
|
||||
<td><input type='text' name='VISIBLE_HOSTNAME'
|
||||
value='@{[ &Header::escape($proxysettings{'VISIBLE_HOSTNAME'}) ]}' /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
END
|
||||
@@ -1075,13 +1075,15 @@ print <<END
|
||||
<td class='base'><a href='/cgi-bin/cachemgr.cgi' target='_blank'>$Lang::tr{'proxy cachemgr'}:</td>
|
||||
<td><input type='checkbox' name='CACHEMGR' $checked{'CACHEMGR'}{'on'} /></td>
|
||||
<td class='base'>$Lang::tr{'advproxy admin mail'}:</td>
|
||||
<td><input type='text' name='ADMIN_MAIL_ADDRESS' value='$proxysettings{'ADMIN_MAIL_ADDRESS'}' /></td>
|
||||
<td><input type='text' name='ADMIN_MAIL_ADDRESS'
|
||||
value='@{[ &Header::escape($proxysettings{'ADMIN_MAIL_ADDRESS'}) ]}' /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'proxy filedescriptors'}: <img src='/blob.gif' alt='*' /></td>
|
||||
<td><input type='text' name='FILEDESCRIPTORS' value='$proxysettings{'FILEDESCRIPTORS'}' size='5' /></td>
|
||||
<td class='base'>$Lang::tr{'proxy admin password'}:</td>
|
||||
<td><input type='text' name='ADMIN_PASSWORD' value='$proxysettings{'ADMIN_PASSWORD'}' /></td>
|
||||
<td><input type='text' name='ADMIN_PASSWORD'
|
||||
value='@{[ &Header::escape($proxysettings{'ADMIN_PASSWORD'}) ]}' /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width='25%'></td> <td width='20%'> </td><td width='25%'> </td><td width='30%'></td>
|
||||
@@ -3977,8 +3979,14 @@ END
|
||||
print FILE " $proxysettings{'VISIBLE_HOSTNAME'}\n\n";
|
||||
}
|
||||
|
||||
if (!($proxysettings{'ADMIN_MAIL_ADDRESS'} eq '')) { print FILE "cache_mgr $proxysettings{'ADMIN_MAIL_ADDRESS'}\n"; }
|
||||
if (!($proxysettings{'ADMIN_PASSWORD'} eq '')) { print FILE "cachemgr_passwd $proxysettings{'ADMIN_PASSWORD'} all\n"; }
|
||||
if (!($proxysettings{'ADMIN_MAIL_ADDRESS'} eq ''))
|
||||
{
|
||||
print FILE "cache_mgr $proxysettings{'ADMIN_MAIL_ADDRESS'}\n";
|
||||
}
|
||||
if (!($proxysettings{'ADMIN_PASSWORD'} eq ''))
|
||||
{
|
||||
print FILE "cachemgr_passwd $proxysettings{'ADMIN_PASSWORD'} all\n";
|
||||
}
|
||||
print FILE "\n";
|
||||
|
||||
print FILE "max_filedescriptors $proxysettings{'FILEDESCRIPTORS'}\n\n";
|
||||
@@ -3994,8 +4002,13 @@ END
|
||||
# login=*:password ($proxysettings{'FORWARD_USERNAME'} eq 'on')
|
||||
if (($proxy1 eq 'YES') || ($proxy1 eq 'PASS'))
|
||||
{
|
||||
$proxysettings{'UPSTREAM_USER'} = &Header::escape($proxysettings{'UPSTREAM_USER'});
|
||||
print FILE " login=$proxysettings{'UPSTREAM_USER'}";
|
||||
if ($proxy1 eq 'YES') { print FILE ":$proxysettings{'UPSTREAM_PASSWORD'}"; }
|
||||
if ($proxy1 eq 'YES')
|
||||
{
|
||||
$proxysettings{'UPSTREAM_PASSWORD'} = &Header::escape($proxysettings{'UPSTREAM_PASSWORD'});
|
||||
print FILE ":$proxysettings{'UPSTREAM_PASSWORD'}";
|
||||
}
|
||||
}
|
||||
elsif ($proxysettings{'FORWARD_USERNAME'} eq 'on') { print FILE " login=*:password"; }
|
||||
|
||||
@@ -4050,15 +4063,7 @@ sub adduser
|
||||
close(FILE);
|
||||
} else {
|
||||
&deluser($str_user);
|
||||
|
||||
my %htpasswd_options = (
|
||||
passwdFile => "$userdb",
|
||||
UseMD5 => 1,
|
||||
);
|
||||
|
||||
my $htpasswd = new Apache::Htpasswd(\%htpasswd_options);
|
||||
|
||||
$htpasswd->htpasswd($str_user, $str_pass);
|
||||
&General::system("/usr/bin/htpasswd", "-bB", "-C 10", "$userdb", "$str_user", "$str_pass");
|
||||
}
|
||||
|
||||
if ($str_group eq 'standard') { open(FILE, ">>$stdgrp");
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2022 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2007-2025 IPFire Team <info@ipfire.org> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
@@ -652,7 +652,7 @@ if ($errormessage) {
|
||||
|
||||
print <<END
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<table width='66%'>
|
||||
<table width='100%'>
|
||||
END
|
||||
;
|
||||
if ( $message ne "" ) {
|
||||
@@ -671,9 +671,11 @@ END
|
||||
END
|
||||
;
|
||||
if (($qossettings{'OUT_SPD'} ne '') && ($qossettings{'INC_SPD'} ne '')) {
|
||||
$qossettings{'OUT_SPD'} = &Header::escape($qossettings{'OUT_SPD'});
|
||||
$qossettings{'INC_SPD'} = &Header::escape($qossettings{'INC_SPD'});
|
||||
print <<END
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<table width='66%'>
|
||||
<table width='100%'>
|
||||
<tr><td colspan='3'>
|
||||
<tr><td width='50%' align='right'>$Lang::tr{'downlink speed'}: <td width='30%' align='left'>$qossettings{'INC_SPD'}
|
||||
<td width='20%' rowspan='2' align='center' valign='middle'><input type='submit' name='ACTIONBW' value='$Lang::tr{'modify'}' />
|
||||
@@ -683,9 +685,11 @@ END
|
||||
;
|
||||
}
|
||||
if (($qossettings{'DEFCLASS_OUT'} ne '') && ($qossettings{'DEFCLASS_INC'} ne '')) {
|
||||
$qossettings{'DEFCLASS_OUT'} = &Header::escape($qossettings{'DEFCLASS_OUT'});
|
||||
$qossettings{'DEFCLASS_INC'} = &Header::escape($qossettings{'DEFCLASS_INC'});
|
||||
print <<END
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<table width='66%'>
|
||||
<table width='100%'>
|
||||
<tr><td colspan='3'><hr />
|
||||
<tr><td width='50%' align='right'>$Lang::tr{'downlink std class'}: <td width='30%' align='left'>$qossettings{'DEFCLASS_INC'}
|
||||
<td width='20%' rowspan='3' align='center' valign='middle'><input type='submit' name='ACTIONDEF' value='$Lang::tr{'modify'}' />
|
||||
@@ -695,7 +699,7 @@ END
|
||||
</table>
|
||||
</form>
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<table width='66%' border='0'>
|
||||
<table width='100%' border='0'>
|
||||
<tr><td width='100%' align='center'>
|
||||
<input type='submit' name='ACTION' value='$Lang::tr{'parentclass add'}' />
|
||||
<input type='submit' name='ACTION' value='$Lang::tr{'status'}' />
|
||||
@@ -740,7 +744,7 @@ sub changedefclasses {
|
||||
&Header::openbox('100%', 'center', $Lang::tr{'std classes'});
|
||||
print <<END
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<table width='66%'>
|
||||
<table width='100%'>
|
||||
<tr><td width='100%' colspan='3'>$Lang::tr{'no filter pass'}
|
||||
<tr><td width='33%' align='right'>$Lang::tr{'download'}:<td width='33%' align='left'><select name='DEFCLASS_INC'>
|
||||
END
|
||||
@@ -781,7 +785,7 @@ sub changebandwidth {
|
||||
print <<END;
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<input type='hidden' name='DEF_OUT_SPD' value='' /><input type='hidden' name='DEF_INC_SPD' value='' />
|
||||
<table width='66%'>
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td width='100%' colspan='2'>$Lang::tr{'down and up speed'}</td>
|
||||
</tr>
|
||||
@@ -843,7 +847,7 @@ sub parentclass {
|
||||
&Header::openbox('100%', 'center', $Lang::tr{'parentclass'});
|
||||
print <<END
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<table width='66%'>
|
||||
<table width='100%'>
|
||||
END
|
||||
;
|
||||
if ( $message ne "" ) {
|
||||
@@ -936,7 +940,7 @@ sub level7rule {
|
||||
&Header::openbox('100%', 'center', $Lang::tr{'Level7 Rule'});
|
||||
print <<END
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<table width='66%'>
|
||||
<table width='100%'>
|
||||
END
|
||||
;
|
||||
if ( $message ne "" ) {
|
||||
@@ -982,7 +986,7 @@ sub portrule {
|
||||
&Header::openbox('100%', 'center', $Lang::tr{'Add Port Rule'});
|
||||
print <<END
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<table width='66%'>
|
||||
<table width='100%'>
|
||||
<tr><td width='100%' colspan='3'>$Lang::tr{'enter data'}
|
||||
<tr><td width='33%' align='right'>$Lang::tr{'protocol'}:
|
||||
<td width='33%' align='left'><select name='PPROT'>
|
||||
@@ -1028,7 +1032,7 @@ sub tosrule {
|
||||
}
|
||||
print <<END
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<table width='66%'>
|
||||
<table width='100%'>
|
||||
END
|
||||
;
|
||||
if ( $message ne "" ) {
|
||||
|
||||
@@ -82,21 +82,21 @@ if ( (($remotesettings{'ACTION'} eq $Lang::tr{'save'}) || ($remotesettings{'ACTI
|
||||
&General::log("SSH Port 222");
|
||||
}
|
||||
|
||||
if ( $remotesettings{'ACTION'} eq $Lang::tr{'ssh tempstart15'} || $remotesettings{'ACTION'} eq $Lang::tr{'ssh tempstart30'} ){
|
||||
if ($remotesettings{'ENABLE_SSH'} eq 'off')
|
||||
{
|
||||
if ( $remotesettings{'ACTION'} eq $Lang::tr{'ssh tempstart15'} || $remotesettings{'ACTION'} eq $Lang::tr{'ssh tempstart30'} ){
|
||||
if ($remotesettings{'ENABLE_SSH'} eq 'off')
|
||||
{
|
||||
&General::system('/usr/bin/touch', "${General::swroot}/remote/enablessh");
|
||||
&General::system('/usr/local/bin/sshctrl');
|
||||
}
|
||||
if ( $remotesettings{'ACTION'} eq $Lang::tr{'ssh tempstart15'} ) { $counter = 900;}
|
||||
elsif ( $remotesettings{'ACTION'} eq $Lang::tr{'ssh tempstart30'} ) { $counter = 1800;}
|
||||
}
|
||||
if ( $remotesettings{'ACTION'} eq $Lang::tr{'ssh tempstart15'} ) { $counter = 900;}
|
||||
elsif ( $remotesettings{'ACTION'} eq $Lang::tr{'ssh tempstart30'} ) { $counter = 1800;}
|
||||
|
||||
system("/usr/local/bin/sshctrl tempstart $counter >/dev/null");
|
||||
}
|
||||
else {
|
||||
system('/usr/local/bin/sshctrl') == 0
|
||||
system("/usr/local/bin/sshctrl tempstart $counter >/dev/null");
|
||||
}
|
||||
else {
|
||||
system('/usr/local/bin/sshctrl') == 0
|
||||
or $errormessage = "$Lang::tr{'bad return code'} " . $?/256;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&General::readhash("${General::swroot}/remote/settings", \%remotesettings);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2010 IPFire Team #
|
||||
# Copyright (C) 2010-2025 IPFire Team <info@ipfire.org> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
@@ -78,6 +78,7 @@ if ($timesettings{'ACTION'} eq $Lang::tr{'save'})
|
||||
if (!($timesettings{'UPDATE_VALUE'} =~ /^\d+$/) || $timesettings{'UPDATE_VALUE'} <= 0)
|
||||
{
|
||||
$errormessage = $Lang::tr{'invalid time period'};
|
||||
$timesettings{'UPDATE_VALUE'} = 0;
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
@@ -287,6 +288,10 @@ print <<END
|
||||
</table>
|
||||
END
|
||||
;
|
||||
|
||||
my $now = strftime($Lang::tr{'timeformat'}, localtime);
|
||||
print "<hr>$Lang::tr{'system time'}: $now";
|
||||
|
||||
&Header::closebox();
|
||||
&Header::openbox('100%',1,$Lang::tr{'ntp sync'});
|
||||
print <<END
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2005-2010 IPFire Team #
|
||||
# Copyright (C) 2005-2025 IPFire Team #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
@@ -576,7 +576,7 @@ if (($uqsettings{'MODE'} eq 'USERQUOTA') && ($uqsettings{'ACTION'} eq $Lang::tr{
|
||||
|
||||
$_ = $uqsettings{'QUOTA_USERS'};
|
||||
chomp; s/\n/|/g;
|
||||
my $quota_users = $_;
|
||||
my $quota_users = &Header::escape($_);
|
||||
|
||||
if ($uqsettings{'QUOTA_USERS'} =~ /\\/)
|
||||
{
|
||||
@@ -936,6 +936,11 @@ if (($besettings{'ACTION'} eq $Lang::tr{'urlfilter install blacklist'}) && ($bes
|
||||
close FILE;
|
||||
|
||||
# XXX uses globbing
|
||||
if(!($besettings{'BE_NAME'} =~ /^[a-zA-Z0-9-_]+$/))
|
||||
{
|
||||
$errormessage = 'Invalid blacklist name (use only alphanumeric characters plus hyphens or underscores)';
|
||||
goto ERROR;
|
||||
}
|
||||
system("rm -f $dbdir/$besettings{'BE_NAME'}/*.db");
|
||||
&General::system("/usr/bin/squidGuard", "-c", "$editdir/install.conf", "-C", "all");
|
||||
# XXX uses globbing
|
||||
@@ -2047,6 +2052,10 @@ foreach $line (@tclist)
|
||||
if ($temp[7] eq 'on') { $time.=$Lang::tr{'urlfilter sun'}; } else { $time.='='; }
|
||||
$time=$time.' '.$temp[8].':'.$temp[9].' to '.$temp[10].':'.$temp[11];
|
||||
|
||||
$temp[12] = &Header::escape($temp[12]);
|
||||
$temp[13] = &Header::escape($temp[13]);
|
||||
$temp[16] = &Header::escape($temp[16]);
|
||||
|
||||
print <<END
|
||||
<td align='center'>$temp[0]</td>
|
||||
<td align='center' nowrap>$time</td>
|
||||
|
||||
1548
html/cgi-bin/wireguard.cgi
Normal file
1548
html/cgi-bin/wireguard.cgi
Normal file
File diff suppressed because it is too large
Load Diff
432
html/cgi-bin/xdpdns.cgi
Normal file
432
html/cgi-bin/xdpdns.cgi
Normal file
@@ -0,0 +1,432 @@
|
||||
#!/usr/bin/perl
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2020 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2024 BPFire <vincent.mc.li@gmail.com> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
use strict;
|
||||
|
||||
# enable only the following on debugging purpose
|
||||
use warnings;
|
||||
use CGI::Carp 'fatalsToBrowser';
|
||||
|
||||
use IO::Socket;
|
||||
|
||||
require '/var/ipfire/general-functions.pl';
|
||||
require "${General::swroot}/location-functions.pl";
|
||||
require "${General::swroot}/lang.pl";
|
||||
require "${General::swroot}/header.pl";
|
||||
|
||||
#workaround to suppress a warning when a variable is used only once
|
||||
my @dummy = ( ${Header::colouryellow} );
|
||||
undef (@dummy);
|
||||
|
||||
my %color = ();
|
||||
my %mainsettings = ();
|
||||
my %settings=();
|
||||
my %checked=();
|
||||
my $errormessage='';
|
||||
my $setting = "${General::swroot}/main/settings";
|
||||
my $xdpdnssettingfile = "${General::swroot}/xdpdns/settings";
|
||||
my $xdpdnsdomainfile = "${General::swroot}/xdpdns/domainfile";
|
||||
|
||||
# Read configuration file.
|
||||
|
||||
&General::readhash("${General::swroot}/main/settings", \%mainsettings);
|
||||
&General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", \%color);
|
||||
|
||||
&Header::showhttpheaders();
|
||||
|
||||
$settings{'ENABLE_DNSBLOCK'} = 'off';
|
||||
$settings{'ACTION'} = '';
|
||||
|
||||
$settings{'KEY1'} = ''; # point record for ACTION
|
||||
$settings{'domainName'} = '';
|
||||
my @nosaved=('domainName', 'KEY1', 'SORT_domainNameLIST');
|
||||
|
||||
#Define each field that can be used to sort columns
|
||||
my $sortstring='^domainName';
|
||||
$settings{'SORT_domainNameLIST'} = 'domainName';
|
||||
|
||||
# Load multiline data
|
||||
our @current = ();
|
||||
if (open(FILE, "$xdpdnsdomainfile")) {
|
||||
@current = <FILE>;
|
||||
close (FILE);
|
||||
}
|
||||
|
||||
&Header::getcgihash(\%settings);
|
||||
|
||||
if ($settings{'ACTION'} eq $Lang::tr{'save'})
|
||||
{
|
||||
|
||||
map (delete ($settings{$_}) ,(@nosaved));
|
||||
&General::writehash("$xdpdnssettingfile", \%settings);
|
||||
|
||||
if ($settings{'ENABLE_DNSBLOCK'} eq 'on') {
|
||||
&General::system('/usr/bin/touch', "${General::swroot}/xdpdns/enablexdpdns");
|
||||
&General::system('/usr/local/bin/xdpdnsctrl', 'start');
|
||||
} else {
|
||||
&General::system('/usr/local/bin/xdpdnsctrl', 'stop');
|
||||
unlink "${General::swroot}/xdpdns/enablexdpdns";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($settings{'ACTION'} eq $Lang::tr{'add'}) {
|
||||
|
||||
#Check for already existing routing entry
|
||||
foreach my $line (@current) {
|
||||
chomp($line); # remove newline
|
||||
#Same domain already used?
|
||||
if($line eq $settings{'domainName'} && $settings{'KEY1'} eq ''){
|
||||
$errormessage = $Lang::tr{'ccd err loxilbconfigeexist'};
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
unless ($errormessage) {
|
||||
if ($settings{'KEY1'} eq '') { #add or edit ?
|
||||
unshift (@current, "$settings{'domainName'}\n");
|
||||
&General::log($Lang::tr{'xdpdns domain added'});
|
||||
} else {
|
||||
@current[$settings{'KEY1'}] = "$settings{'domainName'}\n";
|
||||
$settings{'KEY1'} = ''; # End edit mode
|
||||
&General::log($Lang::tr{'xdpdns domain changed'});
|
||||
}
|
||||
|
||||
&CreateDomain(%settings);
|
||||
|
||||
# Write changes to config file.
|
||||
&SortDataFile; # sort newly added/modified entry
|
||||
|
||||
#map ($settings{$_}='' ,@nosaved); # Clear fields
|
||||
}
|
||||
}
|
||||
|
||||
if ($settings{'ACTION'} eq $Lang::tr{'remove'}) {
|
||||
|
||||
my $line = @current[$settings{'KEY1'}]; # KEY1 is the index in current
|
||||
chomp($line);
|
||||
$settings{'domainName'}=$line;
|
||||
|
||||
&DeleteDomain(%settings);
|
||||
|
||||
splice (@current,$settings{'KEY1'},1); # Delete line
|
||||
open(FILE, ">$xdpdnsdomainfile") or die "$xdpdnsdomainfile open error";
|
||||
print FILE @current;
|
||||
close(FILE);
|
||||
$settings{'KEY1'} = ''; # End remove mode
|
||||
}
|
||||
|
||||
## Check if sorting is asked
|
||||
# If same column clicked, reverse the sort.
|
||||
if ($ENV{'QUERY_STRING'} =~ /$sortstring/ ) {
|
||||
my $newsort=$ENV{'QUERY_STRING'};
|
||||
my $actual=$settings{'SORT_domainNameLIST'};
|
||||
#Reverse actual sort ?
|
||||
if ($actual =~ $newsort) {
|
||||
my $Rev='';
|
||||
if ($actual !~ 'Rev') {
|
||||
$Rev='Rev';
|
||||
}
|
||||
$newsort.=$Rev;
|
||||
}
|
||||
$settings{'SORT_domainNameLIST'}=$newsort;
|
||||
map (delete ($settings{$_}) ,(@nosaved,'ACTION','KEY1'));# Must never be saved
|
||||
&General::writehash($setting, \%settings);
|
||||
&SortDataFile;
|
||||
$settings{'ACTION'} = 'SORT'; # Create an 'ACTION'
|
||||
map ($settings{$_} = '' ,@nosaved,'KEY1'); # and reinit vars to empty
|
||||
}
|
||||
|
||||
if ($settings{'ACTION'} eq '' ) { # First launch from GUI
|
||||
# Place here default value when nothing is initialized
|
||||
$settings{'domainName'} = '';
|
||||
}
|
||||
|
||||
&Header::openpage($Lang::tr{'xdpdns'}, 1, '');
|
||||
|
||||
&Header::openbigbox('100%', 'left', '', $errormessage);
|
||||
|
||||
if ($errormessage) {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'error messages'});
|
||||
print "<font class='base' color=red>$errormessage </font>\n";
|
||||
&Header::closebox();
|
||||
}
|
||||
|
||||
# Read configuration file.
|
||||
&General::readhash("$xdpdnssettingfile", \%settings);
|
||||
|
||||
# Checkbox pre-selection.
|
||||
my $checked;
|
||||
if ($settings{'ENABLE_DNSBLOCK'} eq "on") {
|
||||
$checked = "checked='checked'";
|
||||
}
|
||||
|
||||
my $sactive = "<table cellpadding='2' cellspacing='0' bgcolor='${Header::colourred}' width='50%'><tr><td align='center'><b><font color='#FFFFFF'>$Lang::tr{'stopped'}</font></b></td></tr></table>";
|
||||
|
||||
my @status = &General::system_output('/usr/local/bin/xdpdnsctrl', 'status');
|
||||
|
||||
if (grep(/is attached/, @status)){
|
||||
$sactive = "<table cellpadding='2' cellspacing='0' bgcolor='${Header::colourgreen}' width='50%'><tr><td align='center'><b><font color='#FFFFFF'>$Lang::tr{'running'}</font></b></td></tr></table>";
|
||||
}
|
||||
|
||||
&Header::openbox('100%', 'center', $Lang::tr{'xdpdns status'});
|
||||
|
||||
print <<END;
|
||||
<table width='100%'>
|
||||
<form method='POST' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<td width='25%'> </td>
|
||||
<td width='25%'> </td>
|
||||
<td width='25%'> </td>
|
||||
<tr><td class='boldbase'>$Lang::tr{'xdpdns status'}</td>
|
||||
<td align='left'>$sactive</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width='50%' class='boldbase'>$Lang::tr{'xdpdns enable'}
|
||||
<td><input type='checkbox' name='ENABLE_DNSBLOCK' $checked></td>
|
||||
<td align='center'><input type='submit' name='ACTION' value='$Lang::tr{'save'}'></td>
|
||||
</tr>
|
||||
END
|
||||
|
||||
print "</form> </table>\n";
|
||||
|
||||
&Header::closebox();
|
||||
#
|
||||
|
||||
my $buttontext = $Lang::tr{'add'};
|
||||
if ($settings{'KEY1'} ne '') {
|
||||
$buttontext = $Lang::tr{'update'};
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'xdpdns domain edit'});
|
||||
} else {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'xdpdns domain add'});
|
||||
}
|
||||
|
||||
my @INTERFACES = ("red0", "green0");
|
||||
|
||||
#Edited line number (KEY1) passed until cleared by 'save' or 'remove' or 'new sort order'
|
||||
print <<END;
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<input type='hidden' name='KEY1' value='$settings{'KEY1'}' />
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'xdpdns domain name'}: </td>
|
||||
<td><input type='text' name='domainName' value='$settings{'domainName'}' size='25'/></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
<br>
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td width='50%' align='right'><input type='hidden' name='ACTION' value='$Lang::tr{'add'}' /><input type='submit' name='SUBMIT' value='$buttontext' /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
END
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'xdpdns domain entries'});
|
||||
|
||||
print <<END;
|
||||
|
||||
<table width='100%' class='tbl'>
|
||||
<tr>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?domainName'><b>$Lang::tr{'xdpdns domain name'}</b></a></th>
|
||||
<th width='10%' colspan='3' class='boldbase' align='center'><b>$Lang::tr{'action'}</b></th>
|
||||
</tr>
|
||||
END
|
||||
|
||||
#
|
||||
# Print each line of @current list
|
||||
#
|
||||
|
||||
my $key = 0;
|
||||
my $col="";
|
||||
foreach my $line (@current) {
|
||||
chomp($line); # remove newline
|
||||
|
||||
#Choose icon for checkbox
|
||||
my $gif = '';
|
||||
my $gdesc = '';
|
||||
if ($line ne '' ) {
|
||||
$gif = 'on.gif';
|
||||
$gdesc = $Lang::tr{'click to disable'};
|
||||
} else {
|
||||
$gif = 'off.gif';
|
||||
$gdesc = $Lang::tr{'click to enable'};
|
||||
}
|
||||
|
||||
#Colorize each line
|
||||
if ($settings{'KEY1'} eq $key) {
|
||||
print "<tr bgcolor='${Header::colouryellow}'>";
|
||||
} elsif ($key % 2) {
|
||||
print "<tr>";
|
||||
$col="bgcolor='$color{'color20'}'";
|
||||
} else {
|
||||
print "<tr>";
|
||||
$col="bgcolor='$color{'color22'}'";
|
||||
}
|
||||
print <<END;
|
||||
<td align='center' $col>$line</td>
|
||||
<td align='center' $col>
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<input type='hidden' name='ACTION' value='$Lang::tr{'toggle enable disable'}' />
|
||||
<input type='image' name='$Lang::tr{'toggle enable disable'}' src='/images/$gif' alt='$gdesc' title='$gdesc' />
|
||||
<input type='hidden' name='KEY1' value='$key' />
|
||||
</form>
|
||||
</td>
|
||||
|
||||
<td align='center' $col>
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<input type='hidden' name='ACTION' value='$Lang::tr{'remove'}' />
|
||||
<input type='image' name='$Lang::tr{'remove'}' src='/images/delete.gif' alt='$Lang::tr{'remove'}' title='$Lang::tr{'remove'}' />
|
||||
<input type='hidden' name='KEY1' value='$key' />
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
END
|
||||
|
||||
$key++;
|
||||
}
|
||||
print "</table>";
|
||||
|
||||
# If table contains entries, print 'Key to action icons'
|
||||
if ($key) {
|
||||
print <<END;
|
||||
<table>
|
||||
<tr>
|
||||
<td class='boldbase'> <b>$Lang::tr{'legend'}: </b></td>
|
||||
<td><img src='/images/on.gif' alt='$Lang::tr{'click to disable'}' /></td>
|
||||
<td class='base'>$Lang::tr{'click to disable'}</td>
|
||||
<td> </td>
|
||||
<td><img src='/images/off.gif' alt='$Lang::tr{'click to enable'}' /></td>
|
||||
<td class='base'>$Lang::tr{'click to enable'}</td>
|
||||
<td> </td>
|
||||
<td><img src='/images/delete.gif' alt='$Lang::tr{'remove'}' /></td>
|
||||
<td class='base'>$Lang::tr{'remove'}</td>
|
||||
</tr>
|
||||
</table>
|
||||
END
|
||||
}
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::closebigbox();
|
||||
|
||||
&Header::closepage();
|
||||
|
||||
|
||||
## Ouf it's the end !
|
||||
|
||||
# Sort the "current" array according to choices
|
||||
sub SortDataFile
|
||||
{
|
||||
our %entries = ();
|
||||
|
||||
# Sort pair of record received in $a $b special vars.
|
||||
# When IP is specified use numeric sort else alpha.
|
||||
# If sortname ends with 'Rev', do reverse sort.
|
||||
#
|
||||
sub fixedleasesort {
|
||||
my $qs=''; # The sort field specified minus 'Rev'
|
||||
if (rindex ($settings{'SORT_domainNameLIST'},'Rev') != -1) {
|
||||
$qs=substr ($settings{'SORT_domainNameLIST'},0,length($settings{'SORT_domainNameLIST'})-3);
|
||||
if ($qs eq 'domainName') {
|
||||
my @a = split(/\./,$entries{$a}->{$qs});
|
||||
my @b = split(/\./,$entries{$b}->{$qs});
|
||||
($b[0]<=>$a[0]) ||
|
||||
($b[1]<=>$a[1]) ||
|
||||
($b[2]<=>$a[2]) ||
|
||||
($b[3]<=>$a[3]);
|
||||
} else {
|
||||
$entries{$b}->{$qs} cmp $entries{$a}->{$qs};
|
||||
}
|
||||
} else { #not reverse
|
||||
$qs=$settings{'SORT_domainNameLIST'};
|
||||
if ($qs eq 'domainName') {
|
||||
my @a = split(/\./,$entries{$a}->{$qs});
|
||||
my @b = split(/\./,$entries{$b}->{$qs});
|
||||
($a[0]<=>$b[0]) ||
|
||||
($a[1]<=>$b[1]) ||
|
||||
($a[2]<=>$b[2]) ||
|
||||
($a[3]<=>$b[3]);
|
||||
} else {
|
||||
$entries{$a}->{$qs} cmp $entries{$b}->{$qs};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Use an associative array (%entries)
|
||||
my $key = 0;
|
||||
foreach my $line (@current) {
|
||||
chomp( $line); #remove newline because can be on field 5 or 6 (addition of REMARK)
|
||||
|
||||
# Build a pair 'Field Name',value for each of the data dataline.
|
||||
# Each SORTABLE field must have is pair.
|
||||
# Other data fields (non sortable) can be grouped in one
|
||||
|
||||
my @record = ('KEY',$key++,'domainName',$line);
|
||||
my $record = {}; # create a reference to empty hash
|
||||
%{$record} = @record; # populate that hash with @record
|
||||
$entries{$record->{KEY}} = $record; # add this to a hash of hashes
|
||||
}
|
||||
|
||||
open(FILE, ">$xdpdnsdomainfile") or die "$xdpdnsdomainfile open error";
|
||||
|
||||
# Each field value is printed , with the newline ! Don't forget separator and order of them.
|
||||
foreach my $entry (sort fixedleasesort keys %entries) {
|
||||
print FILE "$entries{$entry}->{domainName}\n";
|
||||
}
|
||||
|
||||
close(FILE);
|
||||
# Reload sorted @current
|
||||
open (FILE, "$xdpdnsdomainfile");
|
||||
@current = <FILE>;
|
||||
close (FILE);
|
||||
}
|
||||
|
||||
sub manageDomain {
|
||||
my ($action, %settings) = @_;
|
||||
|
||||
# Initialize variables
|
||||
my @xdpdns_options;
|
||||
my $command = 'xdp_dns';
|
||||
|
||||
my $domain = $settings{'domainName'};
|
||||
|
||||
push(@xdpdns_options, $action, $domain);
|
||||
|
||||
#debug and display output in UI
|
||||
#my @output = &General::system_output($command, @xdpdns_options);
|
||||
#$errormessage = join('', @output);
|
||||
&General::system($command, @xdpdns_options);
|
||||
|
||||
}
|
||||
|
||||
sub CreateDomain {
|
||||
my (%settings) = @_;
|
||||
manageDomain("add", %settings);
|
||||
}
|
||||
|
||||
sub DeleteDomain {
|
||||
my (%settings) = @_;
|
||||
manageDomain("delete", %settings);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user