108 Commits

Author SHA1 Message Date
Vincent Li
996b80701e keepalived UI: add dummy ip for HA state tracking
add dummy ip 192.0.2.1 in virutal_ipaddress from (TEST-NET-1)
according to https://www.rfc-editor.org/rfc/rfc5737#section-3
for keepalived HA state tracking, the Master will always
have the dummy ip assigned to green0.

add refresh button for HA state refresh

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-07-10 23:25:40 +00:00
Vincent Li
56a1588f96 vim: Disable vim automatic visual mode on mouse select
when mouse select, vim automatically turns into
visual mode, this is not convienent when copy
and paste in vim with mouse select. create this
setting for root user.

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-07-09 02:41:58 +00:00
Vincent Li
aa7d243558 langs: installer/setup Chinese translation
complete the chinese translation referenced below
https://git.ipfire.org/?p=people/ummeegge/ipfire-2.x.git;a=commit;h=ca149dc8e2e24f3cfcf7bbc1e2333b2b6d43e0e4

Asked ChatGPT to translate English in msgid to msgstr in Chinese and
ChatGPT did the translation automatically with correct format.  copied
from ChatGPT and pasted in po.zh

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-07-09 01:47:46 +00:00
Vincent Li
dcb6b5e117 LoxiLB UI: get VIP from ipconfigfile
in HA scenario, the shared/floating VIP
is not configured on the red0 interface

when setup LoxiLB lb from the UI in standby
BPFire, some VIPs are missing since these
VIPs are only configured in the active BPFire.

get VIPs from /var/ipfire/loxilb/ipconfigfile

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-07-09 01:47:46 +00:00
Vincent Li
067bbaf136 LoxiLB: rename UI ipconfig to ipconfigfile
when run loxicmd save -a -c /var/ipfire/loxilb/
ipconfig directory will be created, which conflicts
with loxilb UI that also save virtual ip to
/var/ipfire/loxilb/ipconfig, so rename ipconfig to
ipconfigfile.

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-07-09 01:47:46 +00:00
Vincent Li
02724e7427 LoxiLB: enable firewall SNAT for green network
when loxilb is enabled and started, enable the
firewall SNAT for green network so green network
could have initiate outgoing traffic like internet
access.

we can achieve this by restoring firewall SNAT setting
from default /var/ipfire/loxilb/FWconfig.txt when loxilb
start up with --config-path=/var/ipfire/loxilb thanks
to the enhancement addressed in issue:

https://github.com/loxilb-io/loxilb/issues/706

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-07-09 01:47:46 +00:00
Vincent Li
9f7cd8358f LoxiLB: upgrade to loxilb development branch
LoxiLB 0.9.4 lack of SNAT feature for egress traffic
initiated from BPFire green network, when loxilb is
enabled, it breaks BPFire green network client Internet
access, this issue is fixed in the loxilb development
branch, temporarily I make loxilb development branch
as 0.9.5 in BPFire so I could test the SNAT feature and
it works.

see detail in https://github.com/loxilb-io/loxilb/issues/718

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-07-09 01:47:37 +00:00
Vincent Li
a06eab4ae1 keepalived vs/rs UI: add virtual/real server UI
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-07-05 21:46:07 +00:00
Vincent Li
0f54cfef92 keepalived/ipvs: move ipvsadm to core package
prepare keepalived with ipvs for layer 4
load balancer

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-07-02 20:52:49 +00:00
Vincent Li
fa69bf1da3 openssh: update openssh due to CVE-2024-6387
Update from version 9.7p1 to 9.8p1

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-07-02 19:36:16 +00:00
Vincent Li
e7e1e67fc7 initscripts: start loxilb keepalived after reboot
When loxilb and keepalived are enabled, after BPFire
rebooted, loxilb and keepalived failed to start and
shows as "STOPPED" from UI, this is not expected since
we want to loxilb and keepalived to continue to be enabled
after reboot based on the enabled state of loxilb and
keepalived before reboot.

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-07-01 17:30:54 +00:00
Vincent Li
fae6f15fbe LoxiLB UI: remove @nosaved items
remove @nosaved from /var/ipfire/loxilb/settings
as it could interfere with running state of
loxilb

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-07-01 04:14:51 +00:00
Vincent Li
ebdd4d59b4 keepalived UI: remove @nosaved item
remove @nosaved item from form submission
before writehash to each setting file because
it could interfere with each other.

for example, when change keepalived configuration
for green or red interface from the UI,
without removing @nosaved which has 'ENABLE_HA'
before writehash, 'ENABLE_HA=off' would be saved
in '/var/ipfire/keepalived/settings', this would
trigger the UI to show keepalived being "STOPPED"
or it could actually stopoped keepalived.

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-07-01 00:16:30 +00:00
Vincent Li
6f8ab2d9ec menu: remove pakfire menu
pakfire addon install may cause
conflict with BPFire, remove it
for now.

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-06-30 15:05:49 +00:00
Vincent Li
4363971e05 dhcp: allow user to specify router IP
In BPFire HA deployment, a floating/shared router IP
is required for backend/endpoint server. by default
BPFire uses the primary IP on green0 when running
setup script. Now the floating/shared router IP can
be added to green0 interface as secondary IP through
loxilb UI, keepalived UI can configure the secondary
IP as virtual ipaddress, when HA failover happens,
keepalived will move the virtual ipaddress to new active
BPFire.

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-06-29 20:57:01 +00:00
Vincent Li
2cddcb14f6 keepalived: add keepalivedctrl program
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-06-29 20:57:01 +00:00
Vincent Li
ed89f965bf keepalived UI: add keepalived UI
BPFire red0 does not support multicast, need to
have unicast peer configured, then the virtual
ipaddress can be added to red0 interface.

the UI requires /var/ipfire/keepalived/runsettings
/var/ipfire/keepalived/settings to be created, so
add them lfs/configroot

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-06-29 20:55:28 +00:00
Vincent Li
07750a74ba LoxiLB UI: add required field mark
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-06-29 19:14:30 +00:00
Vincent Li
5955087887 keepalived: move keepalived to core package
change keepalived default config to
/var/ipfire/keepalived/keepalived.conf so keepalived WebUI
could read/write the configuration file. also add
/var/ipfire/keepalived directory

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>

keepalived: create /var/ipfire/keepalived
2024-06-29 19:13:10 +00:00
Vincent Li
61d054216d LoxiLB UI: select virtual ip from red0 interface
since we added loxilb ip management to add ip on
red0 interface, we can select the virtual ip from
red0 interface.

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-06-20 02:49:02 +00:00
Vincent Li
780f556e9c LoxiLB UI: add loxilb ip management
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-06-20 02:48:55 +00:00
Vincent Li
3f1e411f95 move tcpdump and strace to core package
tcpdump and strace are essential for trouble
shooting ship it as core package

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-06-18 03:14:29 +00:00
Vincent Li
7e5fd9e655 Revert "make.sh: change ipfire name to bpfire name"
This reverts commit 2624a47e88.

the name change seems making the iso build downloading
image from upstream ipfire image during instalation. revert
it

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-06-16 02:55:13 +00:00
Vincent Li
8f4062f4da LoxiLB UI: show loxilb server running status
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-06-15 20:52:48 +00:00
Vincent Li
2624a47e88 make.sh: change ipfire name to bpfire name
this change would build iso/img with bpfire name.

note make.sh has toolchain name with ipfire,
so this rename may break something, revert this
commit if running into issue in future.

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-06-15 02:50:17 +00:00
Vincent Li
56461e0173 errormessage: use red color for errormessage
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-06-15 02:14:22 +00:00
Vincent Li
4bbf33e119 LoxiLB: lb config requires lb name
since now we delete lb by name, so lb name
is required field.

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-06-15 00:46:30 +00:00
Vincent Li
e928445c91 LoxiLB: delete lb by name
since loxilb is upgraded to 0.9.4 which allows
loxicmd delete lb by name.

fix: https://github.com/vincentmli/BPFire/issues/26

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-06-14 22:14:16 +00:00
Vincent Li
94f9604493 LoxiLB: remove workaround in loxilbconfig.cgi
now loxilb is upgraded to 0.9.4, it fixes:
https://github.com/vincentmli/BPFire/issues/25

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-06-14 22:06:19 +00:00
Vincent Li
a221be1818 LoxiLB: upgrade loxicmd to 0.9.4
upgrade procedure:

git clone https://github.com/loxilb-io/loxicmd.git
cd loxicmd
git checkout -b v0.9.4 v0.9.4
go mod vendor
cd ..
mv loxicmd loxicmd-0.9.4
tar cvf loxicmd-0.9.4.tar loxicmd-0.9.4
gzip loxicmd-0.9.4.tar
cp loxicmd-0.9.4.tar.gz <BPFire source>/cache/
b2sum <BPFire source>/cache/loxicmd-0.9.4.tar.gz

modify lfs/loxicmd to change the version and b2sum checksum

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-06-14 18:16:43 +00:00
Vincent Li
b9b523d293 Loxilb: upgrade loxilb to 0.9.4
upgrade procedure:

git clone --recurse-submodules https://github.com/loxilb-io/loxilb.git
cd loxilb
git checkout -b v0.9.4 v0.9.4
go mod vendor
cd ..
mv loxilb loxilb-0.9.4
tar cvf loxilb-0.9.4.tar loxilb-0.9.4
gzip loxilb-0.9.4.tar
cp loxilb-0.9.4.tar.gz <BPFire source>/cache/
b2sum <BPFire source>/cache/loxilb-0.9.4.tar.gz

modify lfs/loxilb to change the version and b2sum checksum

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-06-14 18:15:07 +00:00
Vincent Li
0003dd9c8c Loxilb UI: add loxilb firewall UI
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-06-13 04:22:02 +00:00
Vincent Li
63c3e67c07 loxilb UI: fix updating existing LB mode/sel
fix: https://github.com/vincentmli/BPFire/issues/24

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-06-02 01:54:02 +00:00
Vincent Li
6df412401c loxilb UI: add backend monitor option
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-06-01 21:09:54 +00:00
Vincent Li
284b13c137 loxilb UI: use select drop down option
learned from ChatGPT to print dynamic options.
add semi column ';' right after heredoc like:

print <<END;
...
...
END

following result in error

print <<END
...
...
END; #<<<< ERROR

following is correct

print <<END
...
...
END
;

so better use the first format

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-06-01 20:42:16 +00:00
Vincent Li
c946e2d263 README: update load balancer screen shot
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-06-01 14:15:48 +00:00
Vincent Li
8608700ba9 menu: adjust menu titles
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-06-01 14:15:48 +00:00
Vincent Li
6994edf40b Add loxilb lb config UI
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-06-01 14:15:41 +00:00
Vincent Li
f60a419e84 BPFire menu re-arrange
Re-arrange the menu to have BPF centric
main menu, this also easy the developing
of loxilb load balancer GUI since loxilb
will have multiple functions like enable
loxilb, create loxilb lb, create loxilb ip
...etc, so each loxilb function has their
own CGI UI.

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-05-29 18:18:31 +00:00
Vincent Li
280869f883 Do not attach loxilb TC to ethX devices
see [0] loxilb attach TC program to all devices
by default.

[0]:https://github.com/vincentmli/BPFire/issues/22

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-05-28 18:12:51 +00:00
Vincent Li
9c58dcd145 Add WebUI loxilb.cgi for ebpf load balancer
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-05-27 18:23:17 +00:00
Vincent Li
a9c944483b Add loxilb load balancer menu
run command below when update language menu
perl -e "require '/var/ipfire/lang.pl'; &Lang::BuildCacheLang"

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-05-27 18:23:17 +00:00
Vincent Li
61caf1c5eb Add loxilb safe call program
when rebuild image: do

rm log/misc-progs

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-05-27 18:23:17 +00:00
Vincent Li
0c2b510130 add loxilb start/stop init script and settings
when rebuid the image, do:

rm log/configroot
rm log/initscripts

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-05-27 18:23:09 +00:00
Vincent Li
01b41130e5 Update README.md
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-05-17 03:57:24 +00:00
Vincent Li
fb763397b4 loxilb: add loxilb load balancer addon
build loxilb in BPFire requires golang 1.22.0,
but then had issue [0], run go mod vendor to
prepare the loxilb to download golang dependencies
package beforehand to avoid issue [0]

loxilb-ebpf build also requires gnu/stubs-32.h
use [1] as workaround

[0]: https://github.com/vincentmli/BPFire/issues/18
[1]: https://github.com/vincentmli/BPFire/issues/16

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-05-13 18:00:30 +00:00
Vincent Li
a7ed289c04 golang: upgrade from 1.20.4 to 1.22.0
meet loxilb 1.22.0 requirements
see https://github.com/vincentmli/BPFire/issues/19

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-05-13 14:34:14 +00:00
Vincent Li
927b3dfe54 loxicmd addon
Avoid downloading golang dependency packages
during build time due to issue [0], run
go mod vendor so loxicmd source include vendor
directory to include golang dependency packages

[0]: https://github.com/vincentmli/BPFire/issues/18

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-05-13 14:33:10 +00:00
Vincent Li
0000eed295 Add Loxilb ntc and libmd libbsd addon
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-05-11 17:41:01 +00:00
Vincent Li
49df562431 ebpf: Enable kernel BPF_EVENTS
loxilb or other ebpf program could use
bpf_printk for debugging, bpf_printk requires
BPF_EVENTS to be enabled, see [0]

[0] https://github.com/loxilb-io/loxilb/issues/666#issuecomment-2097850413

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-05-08 03:26:51 +00:00
Vincent Li
d544247a53 linux: change kernel NR_CPUS to 512
loxilb MAX_CPUS for cpu_map set to 128, BPFire
original NR_CPUS 64 result in error:

libbpf: map 'cpu_map': failed to create: Argument list too long

see https://github.com/loxilb-io/loxilb/issues/661

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-05-03 16:56:06 +00:00
Vincent Li
04cb6cc6ff libbpf: switch to libbpf 0.8.3
use libbpf 0.8.3 for loxilb

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-05-03 16:52:40 +00:00
Vincent Li
4d35e1845b update README build
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-05-01 20:51:17 +00:00
Vincent Li
c463d1d203 Add DPDK Pktgen 10G SYN flood test throughput 2024-04-28 22:16:45 +00:00
Vincent Li
1aac7c1a4c Add BPFire runnig in Microsoft HyperV pictures
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-04-24 16:27:35 +00:00
Vincent Li
8031d30ad2 ddos init: add ratelimit 2024-04-24 00:48:04 +00:00
Vincent Li
ad771dfe3b ddos.cgi add ratelimit UI 2024-04-24 00:48:04 +00:00
Vincent Li
00cd284e54 Revert "ddos.cgi remove duplicate code"
This reverts commit 8ca6049b32.
2024-04-24 00:48:04 +00:00
Vincent Li
a925c32ecb Revert "ddos.cgi add ratelimit UI"
This reverts commit e3ea91ca5898f0d32cd2733efcd3297d30ffa80e.
2024-04-24 00:48:04 +00:00
Vincent Li
be1fc5ce77 xdp-tools: add xdp-udp
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-04-24 00:48:04 +00:00
Vincent Li
6accd9056f ddos.cgi add ratelimit UI
add ratelimit UI for xdp dns and udp program

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-04-24 00:48:04 +00:00
Vincent Li
1cd908092b Add XDP DDoS README UI screenshot
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-04-24 00:47:52 +00:00
Vincent Li
9d9f3b7afb Add Chinese translation for ddos.cgi
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-04-19 17:15:28 +00:00
Vincent Li
8ca6049b32 ddos.cgi remove duplicate code
improve ddos.cgi by making a few sub routines
to remove duplicate code

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-04-19 17:00:18 +00:00
Vincent Li
fcdc42ea40 ddos.cgi add DNS DDoS UI
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-04-18 02:29:27 +00:00
Vincent Li
56c5212374 firewall.cgi XDP SYNPROXY UI option
only show XDP SYNPROXY option when protocol
TCP is selected.

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-04-17 16:09:54 +00:00
Vincent Li
13bb8928c9 Change header from IPFire_ to BPFire_
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-04-17 01:26:16 +00:00
Vincent Li
0bece3c17a Workaround ddos init script to xdp skb mode
if interface does not support native mode
re-run xdp-loader with skb mode, got error

Attaching XDP program in native mode not supported - try SKB mode.
TCP Native mode not supported, try SKB
Replacing allowed ports
Added port 80
Added port 8090
 libxdp: Retried more than 11 times, giving up
Couldn't attach XDP program on iface 'lo': Device or resource busy(-16)
UDP Native mode not supported, try SKB
Replacing allowed udp ports
Added port 10408

but it looks loaded ok

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-04-17 00:18:34 +00:00
Vincent Li
9924b85773 ddos init script to load/unload TCP/UDP XDP prog
make ddos init script to load/unload TCP/UDP
XDP program according to TCP/UDP setting

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-04-17 00:18:34 +00:00
Vincent Li
8b50f8d07c Rename FireBeeOS to BPFire
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-04-17 00:18:34 +00:00
Vincent Li
9a53289a23 ddos.cgi add UDP DDoS WebUI
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-04-17 00:17:41 +00:00
Vincent Li
6e71870648 ddos.cgi clean up and fix
write to /var/ipfire/ddos/settings file before
enable ddos to allow /etc/rc.d/init.d/ddos script
start up ddos according to the setting from
/var/ipfire/ddos/settings

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-04-14 03:16:53 +00:00
Vincent Li
d7544e6192 Enable kernel BPF without tracing capability
enable kernel BPF XDP/TC capability, no tracing

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-04-09 01:50:14 +00:00
Vincent Li
d9a8ed29e8 Revert "Enable kernel BPF/BTF"
We need to disable BPF trace capability and disallow
unprivileged BPF so

This reverts commit d0bd3cc033.

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-04-08 19:32:11 +00:00
Vincent Li
9f86b661cb Add xdp dns rate limit program with bpf_printk deleted
XDP dns rate limit program has static tail call
which requires revert xdp-tool commit:
(039bdea "xdp-loader: Only load the BPF program we need from object files")

XDP dns rate limit program also uses bpf_printk helper which is not
supported on FireBeeOS since kernel CONFIG_BPF_EVENTS which allows user
to do kprobe, uprobe, tracepoint is not enabled, so bpf_printk helper is
not available, so removed bpf_printk

see discussion in [0] xdp-loader load xdp program with bpf tail call result in Bad file descriptor(-9)

[0] https://github.com/xdp-project/xdp-tools/issues/377

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-04-08 19:15:32 +00:00
Vincent Li
33cc594e39 mount bpffs for xdp-tools for ISO build
xdp-loader will only load the XDP program without
xdp dispatcher if bpffs is not mounted, flash image
has bpffs mounted already, add bpffs mount for ISO image

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-04-07 22:15:12 +00:00
Vincent Li
35f1987b14 Revert "Add ecapture add-on"
This reverts commit 0864b3a5ba.

User might be concerned firewall admin user capture SSL clear
text, so remove ecapture.

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-04-07 15:22:00 +00:00
Vincent Li
ff7a427189 strip kernel module to reduce image size
set strip option to 1 which is to strip modules
debug info. tried to strip all but result in file
system not found during iso installation.

fix: https://github.com/vincentmli/FireBeeOS/issues/3

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-04-06 18:43:15 +00:00
Vincent Li
7b90358c1e Add missing xdp-tools utilities
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-04-06 18:43:15 +00:00
Vincent Li
ef347b3a28 Revert "Enable serial console in default grub"
This reverts commit 7773f82726.

After ISO installation in real hardware and reboot,
the boot process appears to be "stucking" in
"dracut: Switching root".

see https://github.com/vincentmli/FireBeeOS/issues/1

revert the commit resolves the issue, I suspect maybe
the output after "dractu: Switching root" is directed
to serial console? anyway revert this change temporarily.
flash image build still need to have serial console access
for better user experience when trying flash image in KVM/Libvirt
virtual environment.

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-04-06 18:43:15 +00:00
Vincent Li
0c908cf913 Update README with demo link and download link
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-04-06 18:43:08 +00:00
Vincent Li
1688d250dc Add chinese for XDP UI 2024-03-20 17:42:32 +00:00
Vincent Li
8f4b665fb3 populate ddos port map in ddos init script
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-03-20 17:42:31 +00:00
Vincent Li
addfe66863 Change ddos.cgi to call ddosctrl
call ddosctrl with safety from ddos.cgi

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-03-20 17:42:31 +00:00
Vincent Li
9353496864 Add ddosctrl program for safe execution
add ddosctrl to start/stop/status XDP
program from ddos.cgi safely.

permission of ddosctrl

chown root.nobody /usr/local/bin/ddosctrl
chmod u+s /usr/local/bin/ddosctrl

result:

-rwsr-x--- 1 root nobody 14672 Mar 19 09:58 /usr/local/bin/ddosctrl

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-03-20 17:42:30 +00:00
Vincent Li
936c1a4fa0 Add XDP program load/unload script
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-03-20 17:42:30 +00:00
Vincent Li
8e4e24a9b9 Add XDP DDoS ddos.cgi
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-03-20 17:42:07 +00:00
Vincent Li
31f89d1813 Add eBPF XDP DDoS menu
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-03-16 15:54:04 +00:00
Vincent Li
dbb9b7014f fix remote.cgi code style
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-03-16 03:26:26 +00:00
Vincent Li
e48a29a3f1 Add XDP SYNPROXY rules in raw and filter table
XDP SYNPROXY requires setting up iptables rule
in raw table PREROUTING chain and filter table
INPUT chain.

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-03-16 03:26:18 +00:00
Vincent Li
1f16691715 Add custom XDP SYNPROXY chain
XDP SYNPROXY rules needs to be first in filter table
INPUT user defined chain and raw table PREROUTING
user defined chain.

To list the custom chain evaluation order for example:

iptables -L INPUT --line-numbers
Chain INPUT (policy DROP)
num  target     prot opt source               destination
1    INSYNPROXY  all  --  anywhere             anywhere
2    IPSBYPASS  all  --  anywhere             anywhere             mark match 0xc0000000/0xc0000000
3    BADTCP     tcp  --  anywhere             anywhere
4    CUSTOMINPUT  all  --  anywhere             anywhere
5    HOSTILE    all  --  anywhere             anywhere
6    BLOCKLISTIN !icmp --  anywhere             anywhere
7    GUARDIAN   all  --  anywhere             anywhere
8    OVPNBLOCK  all  --  anywhere             anywhere
9    IPS_INPUT  all  --  anywhere             anywhere             mark match 0x0/0xc0000000
10   IPTVINPUT  all  --  anywhere             anywhere
11   ICMPINPUT  all  --  anywhere             anywhere
12   LOOPBACK   all  --  anywhere             anywhere
13   CAPTIVE_PORTAL  all  --  anywhere             anywhere
14   CONNTRACK  all  --  anywhere             anywhere
15   DHCPGREENINPUT  all  --  anywhere             anywhere
16   TOR_INPUT  all  --  anywhere             anywhere
17   LOCATIONBLOCK  all  --  anywhere             anywhere
18   IPSECINPUT  all  --  anywhere             anywhere
19   GUIINPUT   all  --  anywhere             anywhere
20   WIRELESSINPUT  all  --  anywhere             anywhere             ctstate NEW
21   OVPNINPUT  all  --  anywhere             anywhere
22   INPUTFW    all  --  anywhere             anywhere
23   REDINPUT   all  --  anywhere             anywhere
24   POLICYIN   all  --  anywhere             anywhere

iptables -t raw -L PREROUTING --line-numbers

Chain PREROUTING (policy ACCEPT)
num  target     prot opt source               destination
1    RAWSYNPROXY  all  --  anywhere             anywhere

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-03-15 02:56:41 +00:00
Vincent Li
baf1d4a604 Disable vim automatic visual mode on mouse select
when mouse select, vim automatically turns into
visual mode, this is not convienent when copy
and paste in vim with mouse select.

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-03-14 23:50:24 +00:00
Vincent Li
968fd0ca40 make sub routine for various rule check
with routine, we could reuse the code if possible.

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-03-14 23:49:14 +00:00
Vincent Li
852567122e Add XDP SYNPROXY iptables rule UI option
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-03-12 02:41:43 +00:00
Vincent Li
eefbd2ef87 mount bpffs for XDP program
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-03-04 22:15:09 +00:00
Vincent Li
11d2901fc7 Update README with FireBeeOS
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-03-01 04:08:02 +00:00
Vincent Li
0864b3a5ba Add ecapture add-on
Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-03-01 04:08:02 +00:00
Vincent Li
05ac4be397 add bpftool and re-arrange lfs build order
add lfs bpftool from [0] first to meet lfs
xdp-tools requirement.

also re-arrange BPF related add-on build order
to meet lfs knot build since it requires XDP
xsk.h

[0] https://github.com/libbpf/bpftool/releases/download/v7.3.0/bpftool-libbpf-v7.3.0-sources.tar.gz

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-03-01 04:08:02 +00:00
Vincent Li
f8ca312cfa Add xdp-tools add-on with XDP Synproxy
add xdp-tools utilities with addition of
SYN flooding DDoS attack protection in XDP

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-03-01 04:08:02 +00:00
Vincent Li
292ed31c4d Add clang add-on
xdp-tools requires clang, add clang during build
to meet xdp-tools requirement.

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-03-01 04:08:02 +00:00
Vincent Li
5de4e5e9e9 Add pahole during build
add pahole add-on during build to
allow kernel with BPF/BTF enabled
to be built. no need to install pahole
since we only need it during build.

the procedure to prepare pahole tar ball:

download pahole from [0]
untar it and download libbpf from [1]
and untar libbpf

then:

rm pahole-1.25/lib/bpf
mv libbpf-1.3.0 to pahole-1.25/lib/
cd pahole-1.25/lib/
mv libbpf-1.3.0 bpf
cd ../../
tar -czcf pahole-1.25.tar.gz pahole-1.25

mv pahole-1.25.tar.gz ipfire-2.x/cache
b2sum ipfire-2.x/cache/pahole-1.25.tar.gz

Note cmake without optimization -O2 in
lfs/pahole result in _FORTIFY_SOURCE requires
optimzation error since ipfire glibc built
with --enable-fortify-source

this also avoid the hack in [2]

[0]https://git.kernel.org/pub/scm/devel/pahole/pahole.git/snapshot/pahole-1.25.tar.gz
[1]https://github.com/libbpf/libbpf/archive/refs/tags/v1.3.0.tar.gz
[2]https://community.ipfire.org/t/how-to-customize-config-kernel-kernel-config-x86-64-ipfire/11100/8

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-03-01 04:08:02 +00:00
Vincent Li
fc0c2fe6da Add GUI Chinese translation
Add China mainland, China hk, China tw
translation. remember to remove log/configroot
to re-build image with new language support

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-03-01 04:08:01 +00:00
Vincent Li
45f0a5d543 Add lfs libbpf 1.3.0 add-on
follow [0] to add libbpf add-on for bpf user space
program to open,load,attach bpf program.

to build libbpf add-on, follow [1] first, then follow [0]

[0] https://www.ipfire.org/docs/devel/ipfire-2-x/addon-howto
[1] https://www.ipfire.org/docs/devel/ipfire-2-x/build-howto

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-03-01 04:08:01 +00:00
Vincent Li
e97d70d152 Add bpftool
bpftool comes with Linux kernel source and
it is handy to have bpftool on ipfire kernel
with BPF/BTF enabled to diagnosis BPF related
issue.

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-03-01 04:08:01 +00:00
Vincent Li
d0bd3cc033 Enable kernel BPF/BTF
enable kernel BPF/BTF build for ebpf/XDP
program packet filtering

see hack in [1]

[1] https://community.ipfire.org/t/how-to-customize-config-kernel-kernel-config-x86-64-ipfire/11100/7

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-03-01 04:08:01 +00:00
Vincent Li
803c6baaea Increase img build partition size
increase img build partition size for
BPF/BTF enabled kernel

Singed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-03-01 04:08:01 +00:00
Vincent Li
2f621b80d5 Increase build tmpfs size
increase build tmpfs size to prepare space
for building BPF/BTF enabled kernel

Singed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-03-01 04:08:01 +00:00
Vincent Li
7773f82726 Enable serial console in default grub
serial console allows user to easy access
to ipfire image instance in KVM/Libvirt
environment by virt console <ipfire instance>

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-03-01 04:08:01 +00:00
91 changed files with 15061 additions and 272 deletions

View File

@@ -1,29 +1,75 @@
# IPFire 2.x - The Open Source Firewall
# BPFire - eBPF Network Firewall and Load Balancer
# 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, a hardened, versatile, state-of-the-art Open Source firewall based on Linux. BPFire is an eBPF networking centric Linux OS distribution that is easy for users to install and use. 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.
1. XDP DDoS protection, See XDP SYNPROXY stops 10G DDoS SYN flood [here](https://www.youtube.com/watch?v=81Hgoy-x1A4)
2. eBPF based LoxiLB load balancer, overall load balancer features located [here](https://loxilb-io.github.io/loxilbdocs/#overall-features-of-loxilb)
# Where can I get IPFire?
# Where can I get BPFire installation image?
Just head over to https://www.ipfire.org/download
https://drive.google.com/drive/folders/1HPJTWP6wi5gPd5gyiiKvIhWipqguptzZ?usp=drive_link
# How do I use this software?
We have a long and detailed wiki located [here](https://wiki.ipfire.org/) which
should answers most of your questions.
BPFire XDP DDoS feature demo:
[![Enable IPFire eBPF XDP DDoS from WebUI](http://img.youtube.com/vi/1pdNgoP-Kho/0.jpg)](https://www.youtube.com/watch?v=1pdNgoP-Kho "Enable IPFire eBPF XDP DDoS from WebUI")
IPFire have a long and detailed wiki located [here](https://wiki.ipfire.org/) which
should answers most of your questions for IPFire.
# BPFire SYNPROXY throughput with and without XDP acceleration under 10Gbit DDoS SYN flood:
[![Throughput performance](http://img.youtube.com/vi/81Hgoy-x1A4/0.jpg)](https://www.youtube.com/watch?v=81Hgoy-x1A4 "Throughput performance")
# BPFire WebUI screenshot:
English:
![](./images/bpfire-lb-en.png)
![](./images/en-1.png)
![](./images/en-2.png)
Chinese:
![](./images/bpfire-lb-zh.png)
![](./images/cn-1.png)
![](./images/cn-2.png)
# 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:
![](./images/hyperv-1.png)
![](./images/hyperv-2.png)
# 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).
You can ask your question by open github issue report or discussion or
You can ask your question at ipfire community located [here](https://community.ipfire.org/) that is IPFire related.
# How can I contribute?
# How to build BPFire?
We have another document for this. Please look [here](doc/CONTRIBUTING.md).
Build Environment Setup https://www.ipfire.org/docs/devel/ipfire-2-x/build-initial
git clone https://github.com/vincentmli/BPFire.git
cd BPFire
git checkout bpfire
get BPFire source tar balls https://drive.google.com/file/d/1YjTzik4xw0JxFDldLZdVw1GthXG5QrS_/view?usp=drive_link
tar xvf cache.tar
./make.sh build

View File

@@ -0,0 +1,9 @@
22=off
ENABLE_DDOS=off
25=off
80=off
53=off
8080=off
8090=off
443=off
5555=off

View File

@@ -0,0 +1 @@
ENABLE_DNS_DDOS=off

View File

@@ -366,6 +366,14 @@ sub validip
}
}
sub validnum {
my $num = shift;
if ($num =~ /^\d+$/) {
return 1;
}
return 0;
}
sub validmask {
my $mask = shift;
@@ -1306,6 +1314,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;

View File

@@ -0,0 +1 @@
{"fwAttr":[{"opts":{"counter":"0:0","doSnat":true,"toIP":"REDIP"},"ruleArguments":{"destinationIP":"0.0.0.0/0","portName":"green0","sourceIP":"0.0.0.0/0"}}]}

View File

@@ -0,0 +1 @@
ENABLE_LOXILB=off

8
config/cfgroot/tcp_ports Normal file
View 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

View File

@@ -0,0 +1,5 @@
53=off
ENABLE_UDP_DDOS=off
5060=off
5061=off
10408=off

5
config/cfgroot/udp_ports Normal file
View 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

View File

@@ -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;

View File

@@ -0,0 +1,8 @@
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

View File

@@ -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

View File

@@ -22,7 +22,7 @@
'enabled' => 1,
'subMenu' => $subproxy
};
$menu->{'07.ipfire'} = {'caption' => 'IPFire',
$menu->{'07.ipfire'} = {'caption' => 'BPFire',
'enabled' => 1,
'subMenu' => $subipfire
};

View File

@@ -1,8 +1,32 @@
$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->{'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'}",

View File

@@ -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

View File

@@ -0,0 +1,2 @@
usr/sbin/bpftool
usr/share/bash-completion/completions/bpftool

View File

@@ -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
@@ -199,3 +200,5 @@ var/ipfire/wakeonlan
var/ipfire/wireless
#var/ipfire/wireless/config
#var/ipfire/wireless/settings
var/ipfire/ddos
var/ipfire/loxilb

View File

@@ -38,3 +38,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

View File

@@ -0,0 +1,3 @@
usr/include/bpf/xsk.h
usr/lib/libbpf.so.0
usr/lib/libbpf.so.0.8.3

View 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

View 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

View File

@@ -0,0 +1 @@
usr/bin/loxicmd

View 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

View File

@@ -0,0 +1 @@
usr/bin/ntc

View File

@@ -38,3 +38,6 @@ usr/local/bin/urlfilterctrl
usr/local/bin/wirelessclient
usr/local/bin/wirelessctrl
#usr/local/bin/wlanapctrl
usr/local/bin/ddosctrl
usr/local/bin/loxilbctrl
usr/local/bin/keepalivedctrl

View File

@@ -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

View File

@@ -1,4 +1,5 @@
etc/vimrc
root/.vimrc
usr/bin/ex
usr/bin/rview
usr/bin/rvim

View File

@@ -90,6 +90,11 @@ 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/html
srv/web/ipfire/html/blob.gif
#srv/web/ipfire/html/captive

View File

@@ -91,6 +91,8 @@ 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/init.d/loxilb
#etc/rc.d/rc0.d
#etc/rc.d/rc0.d/K01imspetor
#etc/rc.d/rc0.d/K01motion

View File

@@ -23699,3 +23699,4 @@ 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

View File

@@ -0,0 +1,34 @@
usr/lib/bpf/xdp-dispatcher.o
usr/lib/bpf/xdp_synproxy.bpf.o
usr/lib/bpf/xdp_dnsrrl.bpf.o
usr/lib/bpf/xdp_udp.bpf.o
usr/sbin/xdp-udp
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.4.0
usr/lib/pkgconfig/libxdp.pc
usr/sbin/xdp-bench
usr/sbin/xdp-filter
usr/sbin/xdp-loader
usr/sbin/xdp-monitor
usr/sbin/xdp-trafficgen
usr/sbin/xdp_synproxy
usr/sbin/xdp-udp
usr/sbin/xdpdump
usr/share/xdp-tools/xdp_drop.o
usr/share/xdp-tools/xdp_pass.o

1
config/vim/.vimrc Normal file
View File

@@ -0,0 +1 @@
set mouse-=a

546
html/cgi-bin/ddos.cgi Executable file
View 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&nbsp;</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'}'>&nbsp;</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>&nbsp;</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'}'>&nbsp;</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>&nbsp;</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
;
}
}
}

View File

@@ -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'}&nbsp;</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'}&nbsp;<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'}&nbsp;<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='*' />&nbsp;$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}"});

View File

@@ -92,6 +92,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 +130,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 +221,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 +304,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'){
@@ -959,6 +920,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;
@@ -1624,6 +1653,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 +1670,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 +1692,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 +1720,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 +1934,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 +2243,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>
@@ -2341,6 +2387,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 +2429,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;
}
}

376
html/cgi-bin/keepalived.cgi Normal file
View File

@@ -0,0 +1,376 @@
#!/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&nbsp;</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%'>&nbsp;</td>
<td width='25%'>&nbsp;</td>
<td width='25%'>&nbsp;</td>
<tr><td class='boldbase'>$Lang::tr{'keepalived status'}</td>
<td align='left'>$sactive</td>
<td align='center'>$hastate</td>
<td align='right'>
<form method='GET' action='$ENV{'SCRIPT_NAME'}'>
<input type='submit' value='Refresh'>
</form>
</td>
</tr>
<tr>
<td colspan='4'>&nbsp;</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'}:&nbsp;</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'}&nbsp;<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'}&nbsp;<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'}&nbsp;<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'}&nbsp;</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'}&nbsp;<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'}&nbsp;<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'}:&nbsp;<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='*' />&nbsp;$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');
}

View 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 "&nbsp;</class>\n";
&Header::closebox();
}
}
sub hint
{
if ($hint) {
&Header::openbox('100%', 'left', $Lang::tr{'fwhost hint'});
print "<class name='base'>$hint\n";
print "&nbsp;</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();

469
html/cgi-bin/loxilb.cgi Normal file
View File

@@ -0,0 +1,469 @@
#!/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&nbsp;</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%'>&nbsp;</td>
<td width='25%'>&nbsp;</td>
<td width='25%'>&nbsp;</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'}:&nbsp;</td>
<td><input type='text' name='virtualIP' value='$settings{'virtualIP'}' size='25'/></td>
</tr>
<tr>
<td class='base'>$Lang::tr{'loxilb ip interface'}:&nbsp;</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'>&nbsp;<b>$Lang::tr{'legend'}:&nbsp;</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>&nbsp;&nbsp;</td>
<td><img src='/images/off.gif' alt='$Lang::tr{'click to enable'}' /></td>
<td class='base'>$Lang::tr{'click to enable'}</td>
<td>&nbsp;&nbsp;</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 CreateIP {
my (%settings) = @_;
manageIP("create", %settings);
}
sub DeleteIP {
my (%settings) = @_;
manageIP("delete", %settings);
}

View File

@@ -0,0 +1,699 @@
#!/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 "&nbsp;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&nbsp;</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'}&nbsp;<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'}:&nbsp;</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'}&nbsp;<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'}:&nbsp;</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'}:&nbsp;</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'}:&nbsp;</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'}&nbsp;<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'}&nbsp;<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'}:&nbsp;</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='*' />&nbsp;$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'>&nbsp;<b>$Lang::tr{'legend'}:&nbsp;</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>&nbsp;&nbsp;</td>
<td><img src='/images/off.gif' alt='$Lang::tr{'click to enable'}' /></td>
<td class='base'>$Lang::tr{'click to enable'}</td>
<td>&nbsp;&nbsp;</td>
<td><img src='/images/edit.gif' alt='$Lang::tr{'edit'}' /></td>
<td class='base'>$Lang::tr{'edit'}</td>
<td>&nbsp;&nbsp;</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);
}
#
# 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);
}
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);
}

642
html/cgi-bin/loxilbfw.cgi Normal file
View File

@@ -0,0 +1,642 @@
#!/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 "&nbsp;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&nbsp;</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'}&nbsp;<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'}&nbsp;<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'}:&nbsp;</td>
<td><input type='text' name='minSourcePort' value='$settings{'minSourcePort'}' size='25'/></td>
</tr>
<tr>
<td class='base'>$Lang::tr{'loxilb fw maxSourcePort'}:&nbsp;</td>
<td><input type='text' name='maxSourcePort' value='$settings{'maxSourcePort'}' size='25'/></td>
</tr>
<tr>
<td class='base'>$Lang::tr{'loxilb fw minDestinationPort'}:&nbsp;</td>
<td><input type='text' name='minDestinationPort' value='$settings{'minDestinationPort'}' size='25'/></td>
</tr>
<tr>
<td class='base'>$Lang::tr{'loxilb fw maxDestinationPort'}:&nbsp;</td>
<td><input type='text' name='maxDestinationPort' value='$settings{'maxDestinationPort'}' size='25'/></td>
</tr>
<tr>
<td class='base'>$Lang::tr{'loxilb fw proto'}:&nbsp;</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'}:&nbsp;</td>
<td><input type='text' name='portName' value='$settings{'portName'}' size='25'/></td>
</tr>
<tr>
<td class='base'>$Lang::tr{'loxilb fw preference'}:&nbsp;</td>
<td><input type='text' name='preference' value='$settings{'preference'}' size='25'/></td>
</tr>
<tr>
<td class='base'>$Lang::tr{'loxilb fw action'}:&nbsp;</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='*' />&nbsp;$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'>&nbsp;<b>$Lang::tr{'legend'}:&nbsp;</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>&nbsp;&nbsp;</td>
<td><img src='/images/off.gif' alt='$Lang::tr{'click to enable'}' /></td>
<td class='base'>$Lang::tr{'click to enable'}</td>
<td>&nbsp;&nbsp;</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 CreateFW {
my (%settings) = @_;
manageFW("create", %settings);
}
sub DeleteFW {
my (%settings) = @_;
manageFW("delete", %settings);
}

View File

@@ -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);

View File

@@ -142,7 +142,7 @@ print <<END
<div id="logo">
<h1>
<a href="https://www.ipfire.org">
IPFire_
BPFire_
</a>
END
;

BIN
images/bpfire-lb-en.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

BIN
images/bpfire-lb-zh.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

BIN
images/cn-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

BIN
images/cn-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

BIN
images/en-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

BIN
images/en-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

BIN
images/hyperv-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 KiB

BIN
images/hyperv-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

View File

@@ -141,6 +141,7 @@
'activate' => 'Activate',
'activate user' => 'Activate user',
'active' => 'Active',
'standby' => 'Standby',
'add' => 'Add',
'add a host' => 'Add a host',
'add a new rule' => 'Add a new rule:',
@@ -611,6 +612,7 @@
'ccd err invalidnet' => 'Invalid IP address. Format: 192.168.0.0/24 or 192.168.0.0/255.255.255.0.',
'ccd err iroute' => 'Network address for route is invalid.',
'ccd err irouteexist' => 'This route is already in use.',
'ccd err loxilbconfigeexist' => 'This lb is already in use.',
'ccd err isipsecnet' => 'The given subnet address is already used by an IPsec network.',
'ccd err isipsecrw' => 'The given subnet address is already used by the IPsec rw network.',
'ccd err isovpnn2n' => 'The subnet address is already in use for an OpenVPN net-to-net connection.',
@@ -703,7 +705,7 @@
'could not retrieve common name from certificate' => 'Could not retrieve common name from certificate.',
'count' => 'Count',
'countries' => 'Countries',
'country' => 'Country',
'country' => 'Country/Region',
'country codes and flags' => 'Country Codes and Flags:',
'countrycode' => 'Code',
'cpu frequency' => 'CPU frequency',
@@ -1254,6 +1256,7 @@
'fwdfw toggle' => 'Activate or deactivate',
'fwdfw togglelog' => 'Activate or deactivate logging',
'fwdfw use nat' => 'Use Network Address Translation (NAT)',
'fwdfw use synproxy' => 'Use XDP TCP SYNPROXY acceleration:',
'fwdfw use srcport' => 'Source port:',
'fwdfw use srv' => 'Destination port:',
'fwdfw useless rule' => 'This rule is useless.',
@@ -1384,6 +1387,7 @@
'graph per' => 'per',
'green' => 'GREEN',
'green interface' => 'Green Interface',
'red interface' => 'Red Interface',
'grouptype' => 'Grouptype:',
'guaranteed bandwidth' => 'Guaranteed bandwidth',
'guardian' => 'Guardian',
@@ -1510,6 +1514,24 @@
'intrusion detection system rules' => 'Ruleset',
'intrusion detection system2' => 'Intrusion Prevention System',
'intrusion prevention system' => 'Intrusion Prevention System',
'ebpf xdp ddos' => 'eBPF XDP DDoS Protection',
'ebpf xdp ddos system' => 'eBPF XDP DDoS Protection System',
'xdp tcp' => 'XDP TCP',
'xdp udp' => 'XDP UDP',
'xdp dns' => 'XDP DNS',
'xdp enable' => 'Enable DDoS',
'xdp tcp port' => 'TCP Ports',
'xdp udp port' => 'UDP Ports',
'xdp dns ratelimit' => 'DNS Ratelimit:',
'xdp udp ratelimit' => 'UDP Ratelimit:',
'xdp status' => 'XDP Program Status',
'xdp interface' => 'Interface',
'xdp prio' => 'Prio',
'xdp program' => 'Program name',
'xdp mode' => 'Mode',
'xdp id' => 'ID',
'xdp tag' => 'Tag',
'xdp action' => 'Chain actions',
'invalid broadcast ip' => 'Invalid broadcast IP',
'invalid cache size' => 'Invalid cache size.',
'invalid characters found in pre-shared key' => 'Invalid characters found in pre-shared key.',
@@ -1575,6 +1597,7 @@
'invalid secondary dns' => 'Invalid secondary DNS.',
'invalid secondary ntp' => 'Invalid Secondary NTP server address',
'invalid start address' => 'Invalid start address.',
'invalid router address' => 'Invalid router address.',
'invalid time entered' => 'Invalid time entered.',
'invalid time period' => 'Invalid time period',
'invalid uplink speed' => 'Invalid uplink speed.',
@@ -2429,10 +2452,61 @@
'standard login script' => 'Standard login script',
'start' => 'Start',
'start address' => 'Start address:',
'router address' => 'Router address:',
'start ovpn server' => 'Start OpenVPN Server',
'state or province' => 'State or Province',
'static ip' => 'Static IP',
'static routes' => 'Static Routes',
'loxilb' => 'eBPF LoxiLB Load Balancer',
'loxilb status' => 'Status',
'loxilb server status' => 'Current LoxiLB server status:',
'loxilb empty' => 'Field can not be empty',
'loxilb enable' => 'Enable Load Balancer',
'loxilb config' => 'LoxiLB Load Balancer Configuration',
'loxilb lb config changed' => 'LoxiLB LB configuration is changed',
'loxilb lb config added' => 'LoxiLB LB configuration is added',
'loxilb lb config entries' => 'LoxiLB Loadbalaner configuration entries',
'loxilb lb edit' => 'Edit existing lb entry',
'loxilb lb add' => 'Add lb entry',
'loxilb lb name' => 'Name',
'loxilb lb extip' => 'EXTIP',
'loxilb lb port' => 'PORT',
'loxilb lb proto' => 'PROTO',
'loxilb lb sel' => 'SEL',
'loxilb lb mode' => 'MODE',
'loxilb lb endpoints' => 'ENDPOINTS',
'loxilb lb eport' => 'EPORT',
'loxilb lb monitor' => 'MONITOR',
'loxilb fw' => 'LoxiLB Firewall Configuration',
'loxilb fw changed' => 'LoxiLB Firewall Changed',
'loxilb fw entries' => 'LoxiLB Firewall Entries',
'loxilb fw edit' => 'Edit LoxiLB Firewall',
'loxilb fw add' => 'Add LoxiLB Firewall',
'loxilb fw sourceIP' => 'sourceIP',
'loxilb fw destinationIP' => 'destinationIP',
'loxilb fw minSourcePort' => 'minSourcePort',
'loxilb fw maxSourcePort' => 'maxSourcePort',
'loxilb fw minDestinationPort' => 'minDestinationPort',
'loxilb fw maxDestinationPort' => 'maxDestinationPort',
'loxilb fw proto' => 'protocol',
'loxilb fw portName' => 'iport',
'loxilb fw preference' => 'preference',
'loxilb fw action' => 'ruleAction',
'loxilb ip entries' => 'LoxiLB Virtual IP Entries',
'loxilb ip virtualIP' => 'Virtual IP',
'loxilb ip interface' => 'Interface',
'loxilb ip add' => 'Add Virtual IP',
'keepalived' => 'High Availability',
'keepalived config' => 'Keepalived Configuration',
'keepalived status' => 'Keepalived Status',
'keepalived state' => 'State',
'keepalived virtual router id' => 'Virtual Router ID',
'keepalived priority' => 'Priority',
'keepalived advert int' => 'Advert Interval',
'keepalived garp master delay' => 'Garp Master Delay',
'keepalived auth pass' => 'Auth Pass',
'keepalived unicast peer' => 'Unicast Peer',
'keepalived virtual address' => 'Virtual Address',
'status' => 'Status',
'status information' => 'Status information',
'status ovpn' => 'OpenVPN',

3121
langs/hk/cgi-bin/hk.pl Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -7,3 +7,6 @@ ru:Русский:Russian
nl:Nederlands:Dutch
tr:Türkçe:Turkish
it:Italiano:Italian
zh:简体中文:Chinese
hk:繁體中文:中國-香港
tw:繁體中文:中國-台灣

3121
langs/tw/cgi-bin/tw.pl Normal file

File diff suppressed because it is too large Load Diff

3192
langs/zh/cgi-bin/zh.pl Normal file

File diff suppressed because it is too large Load Diff

79
lfs/bpftool Normal file
View File

@@ -0,0 +1,79 @@
###############################################################################
# #
# IPFire.org - A linux based firewall #
# Copyright (C) 2007-2023 IPFire Team <info@ipfire.org> #
# Copyright (C) 2024 FireBeeOS #
# #
# 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/>. #
# #
###############################################################################
###############################################################################
# Definitions
###############################################################################
include Config
VER = 7.3.0
THISAPP = bpftool-$(VER)
DL_FILE = $(THISAPP).tar.gz
DL_FROM = $(URL_IPFIRE)
DIR_APP = $(DIR_SRC)/$(THISAPP)
TARGET = $(DIR_INFO)/$(THISAPP)
###############################################################################
# Top-level Rules
###############################################################################
objects = $(DL_FILE)
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
$(DL_FILE)_BLAKE2 = a9414c92809875c7fa0bd4e38850f5d52ff83cef888b402b49948ea712e192b04e7af7a42da9c0e8bbd53fc7a4bb3cd00ad594dec6f1f3252f6a5cb847697150
install : $(TARGET)
check : $(patsubst %,$(DIR_CHK)/%,$(objects))
download :$(patsubst %,$(DIR_DL)/%,$(objects))
b2 : $(subst %,%_BLAKE2,$(objects))
###############################################################################
# Downloading, checking, b2sum
###############################################################################
$(patsubst %,$(DIR_CHK)/%,$(objects)) :
@$(CHECK)
$(patsubst %,$(DIR_DL)/%,$(objects)) :
@$(LOAD)
$(subst %,%_BLAKE2,$(objects)) :
@$(B2SUM)
###############################################################################
# Installation Details
###############################################################################
$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
@$(PREBUILD)
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar zxf $(DIR_DL)/$(DL_FILE)
cd $(DIR_APP)/src && sed -i -e 's/^prefix ?= \/usr\/local/prefix ?= \/usr/' Makefile
cd $(DIR_APP)/src && make $(MAKETUNING)
cd $(DIR_APP)/src && make install
@rm -rf $(DIR_APP)
@$(POSTBUILD)

View File

@@ -54,7 +54,7 @@ $(TARGET) :
ethernet extrahd/bin fwlogs fwhosts firewall ipblocklist key langs logging mac main \
menu.d modem optionsfw \
ovpn patches pakfire portfw ppp private proxy/advanced/cre \
proxy/calamaris/bin qos/bin red remote sensors suricata time \
proxy/calamaris/bin qos/bin red remote ddos loxilb keepalived sensors suricata time \
updatexlrator/bin updatexlrator/autocheck urlfilter/autoupdate urlfilter/bin vpn \
wakeonlan wireless ; do \
mkdir -p $(CONFIG_ROOT)/$$i; \
@@ -68,7 +68,7 @@ $(TARGET) :
fwhosts/customnetworks fwhosts/customhosts fwhosts/customgroups fwhosts/customservicegrp fwhosts/customlocationgrp fwlogs/ipsettings fwlogs/portsettings ipblocklist/modified \
ipblocklist/settings mac/settings main/hosts main/routing main/security main/settings optionsfw/settings \
ovpn/ccd.conf ovpn/ccdroute ovpn/ccdroute2 pakfire/settings portfw/config ppp/settings-1 ppp/settings-2 ppp/settings-3 ppp/settings-4 \
ppp/settings-5 ppp/settings proxy/settings proxy/squid.conf proxy/advanced/settings proxy/advanced/cre/enable remote/settings qos/settings qos/classes qos/subclasses qos/level7config qos/portconfig \
ppp/settings-5 ppp/settings proxy/settings proxy/squid.conf proxy/advanced/settings proxy/advanced/cre/enable remote/settings ddos/settings ddos/tcp_ports ddos/udp-ddos-settings ddos/udp_ports ddos/dns-ddos-settings loxilb/settings keepalived/keepalived.conf keepalived/runsettings keepalived/settings keepalived/configvs keepalived/configrs qos/settings qos/classes qos/subclasses qos/level7config qos/portconfig \
qos/tosconfig suricata/settings vpn/config vpn/settings vpn/ipsec.conf \
vpn/ipsec.secrets vpn/caconfig wakeonlan/clients.conf wireless/config wireless/settings; do \
touch $(CONFIG_ROOT)/$$i; \
@@ -98,6 +98,13 @@ $(TARGET) :
cp $(DIR_SRC)/config/cfgroot/main-settings $(CONFIG_ROOT)/main/settings
cp $(DIR_SRC)/config/cfgroot/manualpages $(CONFIG_ROOT)/main/
cp $(DIR_SRC)/config/cfgroot/ssh-settings $(CONFIG_ROOT)/remote/settings
cp $(DIR_SRC)/config/cfgroot/ddos-settings $(CONFIG_ROOT)/ddos/settings
cp $(DIR_SRC)/config/cfgroot/tcp_ports $(CONFIG_ROOT)/ddos/tcp_ports
cp $(DIR_SRC)/config/cfgroot/udp-ddos-settings $(CONFIG_ROOT)/ddos/udp-ddos-settings
cp $(DIR_SRC)/config/cfgroot/udp_ports $(CONFIG_ROOT)/ddos/udp_ports
cp $(DIR_SRC)/config/cfgroot/dns-ddos-settings $(CONFIG_ROOT)/ddos/dns-ddos-settings
cp $(DIR_SRC)/config/cfgroot/loxilb-settings $(CONFIG_ROOT)/loxilb/settings
cp $(DIR_SRC)/config/cfgroot/loxilb-FWconfig.txt $(CONFIG_ROOT)/loxilb/FWconfig.txt
cp $(DIR_SRC)/config/cfgroot/time-settings $(CONFIG_ROOT)/time/settings
cp $(DIR_SRC)/config/cfgroot/logging-settings $(CONFIG_ROOT)/logging/settings
cp $(DIR_SRC)/config/cfgroot/ethernet-vlans $(CONFIG_ROOT)/ethernet/vlans

View File

@@ -39,6 +39,7 @@ PART_ROOT = /dev/mapper/$(patsubst /dev/%,%,$(DEVICE))p3
IMAGE_FILE = /install/images/$(SNAME)-$(VERSION)-core$(CORE)-$(BUILD_ARCH).img.xz
FSTAB_FMT = UUID=%s %-8s %-4s %-10s %d %d\n
BPFFS_FMT = %s %-8s %-4s %-10s %d %d\n
###############################################################################
# Top-level Rules
@@ -80,7 +81,7 @@ endif
# /boot: 512 MB - OFFSET
# / : 1800 MB
S_BOOT := $(shell echo $$(( 1048576 - $(S_OFFSET) )))
S_ROOT := 3773292
S_ROOT := 11319876
ifeq "$(EFI)" "1"
S_EFI = 65536 # 32 MB
@@ -166,6 +167,9 @@ endif
printf "$(FSTAB_FMT)" "$$(blkid -o value -s UUID $(PART_ROOT))" "/" \
"auto" "defaults" 1 1 >> $(MNThdd)/etc/fstab
printf "$(BPFFS_FMT)" "bpffs" "/sys/fs/bpf" \
"bpf" "defaults" 0 0 >> $(MNThdd)/etc/fstab
ifeq "$(BOOTLOADER)" "grub"
# backup defaults file
cp $(MNThdd)/etc/default/grub $(MNThdd)/etc/default/grub.backup

4
lfs/go
View File

@@ -24,7 +24,7 @@
include Config
VER = 1.20.4
VER = 1.22.0
THISAPP = go-$(VER)
DL_FILE = go$(VER).$(GOOS)-$(GOARCH).tar.gz
@@ -42,7 +42,7 @@ objects = $(DL_FILE)
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
go$(VER).$(GOOS)-arm64.tar.gz_BLAKE2 = 330336e36ebc7cb8666159256ff6dce965465195db84e29467fe0ffa79b1fa1b698d8751df73bec1cd7d04b528d9d6a9cad259f6ad5036eb89212ebc3e91b686
go$(VER).$(GOOS)-amd64.tar.gz_BLAKE2 = 38cca2ef6d5b9f2ef8c3cef6726930be790bde5ee8693a22f15cad2d96212967c52de9361c996f0a7a91f3b28de83e40a9eca3618167bb1340978daf5e104cdf
go$(VER).$(GOOS)-amd64.tar.gz_BLAKE2 = 018b9dd68d12ed0f2859993b6496d95bec946031353da022eb7fff2337c6082aadabbb4f858987d854599c1c2491e7ca404a7273bde01d61a2491097b24ce1b6
install : $(TARGET)

View File

@@ -135,6 +135,8 @@ $(TARGET) :
ln -sf ../init.d/imspetor /etc/rc.d/rc3.d/S99imspetor
ln -sf ../init.d/motion /etc/rc.d/rc3.d/S99motion
ln -sf ../init.d/vdradmin /etc/rc.d/rc3.d/S99vdradmin
ln -sf ../init.d/loxilb /etc/rc.d/rc3.d/S100loxilb
ln -sf ../init.d/keepalived /etc/rc.d/rc3.d/S101keepalived
ln -sf ../init.d/imspetor /etc/rc.d/rc6.d/K01imspetor
ln -sf ../init.d/motion /etc/rc.d/rc6.d/K01motion

View File

@@ -82,7 +82,7 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
@$(PREBUILD)
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar axf $(DIR_DL)/$(DL_FILE)
cd $(DIR_APP) && ./configure --prefix=/usr --sysconfdir=/etc \
--with-kernel-dir=/usr
--with-kernel-dir=/usr --with-default-config-file=/var/ipfire/keepalived/keepalived.conf
cd $(DIR_APP) && make $(MAKETUNING)
cd $(DIR_APP) && make install

77
lfs/libbpf Normal file
View File

@@ -0,0 +1,77 @@
###############################################################################
# #
# IPFire.org - A linux based firewall #
# Copyright (C) 2007-2023 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/>. #
# #
###############################################################################
###############################################################################
# Definitions
###############################################################################
include Config
VER = 0.8.3
THISAPP = libbpf-$(VER)
DL_FILE = $(THISAPP).tar.gz
DL_FROM = $(URL_IPFIRE)
DIR_APP = $(DIR_SRC)/$(THISAPP)
TARGET = $(DIR_INFO)/$(THISAPP)
###############################################################################
# Top-level Rules
###############################################################################
objects = $(DL_FILE)
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
$(DL_FILE)_BLAKE2 = abee71b4ae0d3a7d0cdf4c108091821d915d4712820dae3debe84b897e7fb84a2c763df508eb539bb74e7461ca2b6836325b7a3c08c6bc8aafe1ac4097614f31
install : $(TARGET)
check : $(patsubst %,$(DIR_CHK)/%,$(objects))
download :$(patsubst %,$(DIR_DL)/%,$(objects))
b2 : $(subst %,%_BLAKE2,$(objects))
###############################################################################
# Downloading, checking, b2sum
###############################################################################
$(patsubst %,$(DIR_CHK)/%,$(objects)) :
@$(CHECK)
$(patsubst %,$(DIR_DL)/%,$(objects)) :
@$(LOAD)
$(subst %,%_BLAKE2,$(objects)) :
@$(B2SUM)
###############################################################################
# Installation Details
###############################################################################
$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
@$(PREBUILD)
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar zxf $(DIR_DL)/$(DL_FILE)
cd $(DIR_APP)/src && make $(MAKETUNING)
cd $(DIR_APP)/src && make install
@rm -rf $(DIR_APP)
@$(POSTBUILD)

78
lfs/libbsd Normal file
View File

@@ -0,0 +1,78 @@
###############################################################################
# #
# IPFire.org - A linux based firewall #
# Copyright (C) 2007-2024 IPFire Team <info@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/>. #
# #
###############################################################################
###############################################################################
# Definitions
###############################################################################
include Config
VER = 0.12.2
THISAPP = libbsd-$(VER)
DL_FILE = $(THISAPP).tar.xz
DL_FROM = $(URL_IPFIRE)
DIR_APP = $(DIR_SRC)/$(THISAPP)
TARGET = $(DIR_INFO)/$(THISAPP)
###############################################################################
# Top-level Rules
###############################################################################
objects = $(DL_FILE)
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
$(DL_FILE)_BLAKE2 = 23a7ebce8e9426be9fc21f90fb957925095d8a4d244434ea07347c9fba4931485c8bb0b20ea84ab7da718d7ceba3bcca20a96f365063813309b82bd351ab223e
install : $(TARGET)
check : $(patsubst %,$(DIR_CHK)/%,$(objects))
download :$(patsubst %,$(DIR_DL)/%,$(objects))
b2 : $(subst %,%_BLAKE2,$(objects))
###############################################################################
# Downloading, checking, b2sum
###############################################################################
$(patsubst %,$(DIR_CHK)/%,$(objects)) :
@$(CHECK)
$(patsubst %,$(DIR_DL)/%,$(objects)) :
@$(LOAD)
$(subst %,%_BLAKE2,$(objects)) :
@$(B2SUM)
###############################################################################
# Installation Details
###############################################################################
$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
@$(PREBUILD)
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar axf $(DIR_DL)/$(DL_FILE)
cd $(DIR_APP) && ./configure --prefix=/usr
cd $(DIR_APP) && make $(MAKETUNING)
cd $(DIR_APP) && make install
@rm -rf $(DIR_APP)
@$(POSTBUILD)

78
lfs/libmd Normal file
View File

@@ -0,0 +1,78 @@
###############################################################################
# #
# IPFire.org - A linux based firewall #
# Copyright (C) 2007-2024 IPFire Team <info@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/>. #
# #
###############################################################################
###############################################################################
# Definitions
###############################################################################
include Config
VER = 1.1.0
THISAPP = libmd-$(VER)
DL_FILE = $(THISAPP).tar.xz
DL_FROM = $(URL_IPFIRE)
DIR_APP = $(DIR_SRC)/$(THISAPP)
TARGET = $(DIR_INFO)/$(THISAPP)
###############################################################################
# Top-level Rules
###############################################################################
objects = $(DL_FILE)
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
$(DL_FILE)_BLAKE2 = a4dc72be4a46609d41453b19ba3110043e74fd0810d59f872e11151dbe87b0bdab203ef72c9d19255db32493b229bc0d33549e787979a42db08c838a810e1cdc
install : $(TARGET)
check : $(patsubst %,$(DIR_CHK)/%,$(objects))
download :$(patsubst %,$(DIR_DL)/%,$(objects))
b2 : $(subst %,%_BLAKE2,$(objects))
###############################################################################
# Downloading, checking, b2sum
###############################################################################
$(patsubst %,$(DIR_CHK)/%,$(objects)) :
@$(CHECK)
$(patsubst %,$(DIR_DL)/%,$(objects)) :
@$(LOAD)
$(subst %,%_BLAKE2,$(objects)) :
@$(B2SUM)
###############################################################################
# Installation Details
###############################################################################
$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
@$(PREBUILD)
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar axf $(DIR_DL)/$(DL_FILE)
cd $(DIR_APP) && ./configure --prefix=/usr
cd $(DIR_APP) && make $(MAKETUNING)
cd $(DIR_APP) && make install
@rm -rf $(DIR_APP)
@$(POSTBUILD)

View File

@@ -157,7 +157,9 @@ else
# Cleanup kernel source
cp $(DIR_SRC)/config/kernel/kernel.config.$(BUILD_ARCH)-$(VERSUFIX) $(DIR_APP)/.config
cp $(DIR_SRC)/config/kernel/kernel.config.bpf $(DIR_APP)/bpf-config
cd $(DIR_APP) && make oldconfig
cd $(DIR_APP) && ./scripts/kconfig/merge_config.sh .config bpf-config
cd $(DIR_APP) && make clean
cd $(DIR_APP) && sed -i -e 's/EXTRAVERSION\ =.*/EXTRAVERSION\ =\ -$(VERSUFIX)/' Makefile
@@ -170,11 +172,18 @@ else
# Build the kernel
cd $(DIR_APP) && make $(MAKETUNING) $(KERNEL_TARGET) modules
# Build bpftool
cd $(DIR_APP)/tools/bpf/bpftool && sed -i -e 's/^prefix ?= \/usr\/local/prefix ?= \/usr/' Makefile
cd $(DIR_APP)/tools/bpf/bpftool && make $(MAKETUNING)
# Install the kernel
cd $(DIR_APP) && cp -v arch/$(KERNEL_ARCH)/boot/$(KERNEL_TARGET) /boot/vmlinuz-$(VER)-$(VERSUFIX)
cd $(DIR_APP) && cp -v System.map /boot/System.map-$(VER)-$(VERSUFIX)
cd $(DIR_APP) && cp -v .config /boot/config-$(VER)-$(VERSUFIX)
cd $(DIR_APP) && make $(MAKETUNING) modules_install
cd $(DIR_APP) && INSTALL_MOD_STRIP=1 make $(MAKETUNING) modules_install
# Install bpftool
cd $(DIR_APP)/tools/bpf/bpftool && make install
ifneq "$(BUILD_PLATFORM)" "x86"
cd $(DIR_APP) && make $(MAKETUNING) dtbs

85
lfs/llvm-project Normal file
View File

@@ -0,0 +1,85 @@
###############################################################################
# #
# IPFire.org - A linux based firewall #
# Copyright (C) 2007-2023 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/>. #
# #
###############################################################################
###############################################################################
# Definitions
###############################################################################
include Config
VER = 17.0.6
THISAPP = llvm-project-$(VER)
DL_FILE = $(THISAPP).tar.gz
DL_FROM = $(URL_IPFIRE)
DIR_APP = $(DIR_SRC)/$(THISAPP)
TARGET = $(DIR_INFO)/$(THISAPP)
###############################################################################
# Top-level Rules
###############################################################################
objects = $(DL_FILE)
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
$(DL_FILE)_BLAKE2 = 779a428c86b5e797a1f2264e33268d69799cf7d9eb9776c38af5efca2b5b6f94248bb48409306fbd61f0d4775ee7ada3cac5490b0bd55d8f56133af1df814b07
install : $(TARGET)
check : $(patsubst %,$(DIR_CHK)/%,$(objects))
download :$(patsubst %,$(DIR_DL)/%,$(objects))
b2 : $(subst %,%_BLAKE2,$(objects))
###############################################################################
# Downloading, checking, b2sum
###############################################################################
$(patsubst %,$(DIR_CHK)/%,$(objects)) :
@$(CHECK)
$(patsubst %,$(DIR_DL)/%,$(objects)) :
@$(LOAD)
$(subst %,%_BLAKE2,$(objects)) :
@$(B2SUM)
###############################################################################
# Installation Details
###############################################################################
$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
@$(PREBUILD)
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar zxf $(DIR_DL)/$(DL_FILE)
cd $(DIR_APP)/llvm && mkdir build
cd $(DIR_APP)/llvm/build && cmake .. -G "Ninja" -DLLVM_TARGETS_TO_BUILD="BPF;X86" \
-DLLVM_ENABLE_PROJECTS="clang" \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_BUILD_RUNTIME=OFF \
-DCMAKE_INSTALL_PREFIX=/usr
cd $(DIR_APP)/llvm/build && ninja
cd $(DIR_APP)/llvm/build && ninja install
@rm -rf $(DIR_APP)
@$(POSTBUILD)

78
lfs/loxicmd Normal file
View File

@@ -0,0 +1,78 @@
###############################################################################
# #
# IPFire.org - A linux based firewall #
# Copyright (C) 2007-2024 IPFire Team <info@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/>. #
# #
###############################################################################
###############################################################################
# Definitions
###############################################################################
include Config
VER = 0.9.5
THISAPP = loxicmd-$(VER)
DL_FILE = $(THISAPP).tar.gz
DL_FROM = $(URL_IPFIRE)
DIR_APP = $(DIR_SRC)/$(THISAPP)
TARGET = $(DIR_INFO)/$(THISAPP)
###############################################################################
# Top-level Rules
###############################################################################
objects = $(DL_FILE)
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
$(DL_FILE)_BLAKE2 = 76e9315ddd791a1bbaf4cd2fbf5a646e93eca3963f46a78efe21d93a31906d01cf318e0aa930d3b4623eec786d83b4a6c7860ee21d65e5f66eb274e107b363b9
install : $(TARGET)
check : $(patsubst %,$(DIR_CHK)/%,$(objects))
download :$(patsubst %,$(DIR_DL)/%,$(objects))
b2 : $(subst %,%_BLAKE2,$(objects))
###############################################################################
# Downloading, checking, b2sum
###############################################################################
$(patsubst %,$(DIR_CHK)/%,$(objects)) :
@$(CHECK)
$(patsubst %,$(DIR_DL)/%,$(objects)) :
@$(LOAD)
$(subst %,%_BLAKE2,$(objects)) :
@$(B2SUM)
###############################################################################
# Installation Details
###############################################################################
$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
@$(PREBUILD)
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar zxf $(DIR_DL)/$(DL_FILE)
cd $(DIR_APP) && make
cd $(DIR_APP) && cp -f loxicmd /usr/bin/loxicmd
@rm -rf $(DIR_APP)
@$(POSTBUILD)

82
lfs/loxilb Normal file
View File

@@ -0,0 +1,82 @@
###############################################################################
# #
# IPFire.org - A linux based firewall #
# Copyright (C) 2007-2024 IPFire Team <info@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/>. #
# #
###############################################################################
###############################################################################
# Definitions
###############################################################################
include Config
VER = 0.9.5
THISAPP = loxilb-$(VER)
DL_FILE = $(THISAPP).tar.gz
DL_FROM = $(URL_IPFIRE)
DIR_APP = $(DIR_SRC)/$(THISAPP)
TARGET = $(DIR_INFO)/$(THISAPP)
###############################################################################
# Top-level Rules
###############################################################################
objects = $(DL_FILE)
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
$(DL_FILE)_BLAKE2 = b1c6b3d25543b5a4c1516e1dc35dbe393c1bd10d8b83307a857713e8ee3553690ce64ffb9d611452c68745564afc775363c90d96b53607902afe24a7d72bdcf7
install : $(TARGET)
check : $(patsubst %,$(DIR_CHK)/%,$(objects))
download :$(patsubst %,$(DIR_DL)/%,$(objects))
b2 : $(subst %,%_BLAKE2,$(objects))
###############################################################################
# Downloading, checking, b2sum
###############################################################################
$(patsubst %,$(DIR_CHK)/%,$(objects)) :
@$(CHECK)
$(patsubst %,$(DIR_DL)/%,$(objects)) :
@$(LOAD)
$(subst %,%_BLAKE2,$(objects)) :
@$(B2SUM)
###############################################################################
# Installation Details
###############################################################################
$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
@$(PREBUILD)
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar zxf $(DIR_DL)/$(DL_FILE)
@rm -rf /opt/loxilb
cd $(DIR_APP) && mkdir -p /opt/loxilb/dp
cd $(DIR_APP) && make
cd $(DIR_APP)/loxilb-ebpf/kernel && cp -f *.o /opt/loxilb/
cd $(DIR_APP) && cp -f loxilb /usr/bin/loxilb
@rm -rf $(DIR_APP)
@$(POSTBUILD)

80
lfs/loxilb-tc Normal file
View File

@@ -0,0 +1,80 @@
###############################################################################
# #
# IPFire.org - A linux based firewall #
# Copyright (C) 2007-2024 IPFire Team <info@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/>. #
# #
###############################################################################
###############################################################################
# Definitions
###############################################################################
include Config
VER = 5.11.0
THISAPP = loxilb-tc-$(VER)
DL_FILE = $(THISAPP).tar.gz
DL_FROM = $(URL_IPFIRE)
DIR_APP = $(DIR_SRC)/$(THISAPP)
TARGET = $(DIR_INFO)/$(THISAPP)
###############################################################################
# Top-level Rules
###############################################################################
objects = $(DL_FILE)
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
$(DL_FILE)_BLAKE2 = 07ff73f6ee40ad8f4d8e74fcd42dc9adf5b1b6ed145ff0c505524913f6362d6a39510c30f9b22b2e8c7ed9a0e14875b2417068edb379c2af1feb9639edd0dd11
install : $(TARGET)
check : $(patsubst %,$(DIR_CHK)/%,$(objects))
download :$(patsubst %,$(DIR_DL)/%,$(objects))
b2 : $(subst %,%_BLAKE2,$(objects))
###############################################################################
# Downloading, checking, b2sum
###############################################################################
$(patsubst %,$(DIR_CHK)/%,$(objects)) :
@$(CHECK)
$(patsubst %,$(DIR_DL)/%,$(objects)) :
@$(LOAD)
$(subst %,%_BLAKE2,$(objects)) :
@$(B2SUM)
###############################################################################
# Installation Details
###############################################################################
$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
@$(PREBUILD)
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar zxf $(DIR_DL)/$(DL_FILE)
cd $(DIR_APP)/libbpf/src/ && mkdir build && DESTDIR=build OBJDIR=build make install
cd $(DIR_APP) && export PKG_CONFIG_PATH=$(DIR_APP)/libbpf/src/ && \
LIBBPF_FORCE=on LIBBPF_DIR=$(DIR_APP)/libbpf/src/build ./configure --prefix=/usr
cd $(DIR_APP) && make $(MAKETUNING)
cd $(DIR_APP) && cp -f tc/tc /usr/bin/ntc
@rm -rf $(DIR_APP)
@$(POSTBUILD)

View File

@@ -24,7 +24,7 @@
include Config
VER = 9.6p1
VER = 9.8p1
THISAPP = openssh-$(VER)
DL_FILE = $(THISAPP).tar.gz
@@ -40,7 +40,7 @@ objects = $(DL_FILE)
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
$(DL_FILE)_BLAKE2 = dd7f6747fe89f7b386be4faaf7fc43398a9bf439e45608ae61c2126cf8743c64ef7b5af45c75e9007b0bda525f8809261ca0f2fc47ce60177ba769a5324719dd
$(DL_FILE)_BLAKE2 = 3bf983c4ef5358054ed0104cd51d3e0069fbc2b80d8522d0df644d5508ec1d26a67bf061b1b5698d1cdf0d2cbba16b4cdca12a4ce30da24429094576a075e192
install : $(TARGET)

78
lfs/pahole Normal file
View File

@@ -0,0 +1,78 @@
###############################################################################
# #
# IPFire.org - A linux based firewall #
# Copyright (C) 2007-2023 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/>. #
# #
###############################################################################
###############################################################################
# Definitions
###############################################################################
include Config
VER = 1.25
THISAPP = pahole-$(VER)
DL_FILE = $(THISAPP).tar.gz
DL_FROM = $(URL_IPFIRE)
DIR_APP = $(DIR_SRC)/$(THISAPP)
TARGET = $(DIR_INFO)/$(THISAPP)
###############################################################################
# Top-level Rules
###############################################################################
objects = $(DL_FILE)
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
$(DL_FILE)_BLAKE2 = dc608dc6b689b3f243cd7349b83e4d6f7b641f99c8c182920a05c4fec396390ae3d3349d65d50724d1c9ee1eab2748b2d6fb05f59231f28c538c9a545ae63c09
install : $(TARGET)
check : $(patsubst %,$(DIR_CHK)/%,$(objects))
download :$(patsubst %,$(DIR_DL)/%,$(objects))
b2 : $(subst %,%_BLAKE2,$(objects))
###############################################################################
# Downloading, checking, b2sum
###############################################################################
$(patsubst %,$(DIR_CHK)/%,$(objects)) :
@$(CHECK)
$(patsubst %,$(DIR_DL)/%,$(objects)) :
@$(LOAD)
$(subst %,%_BLAKE2,$(objects)) :
@$(B2SUM)
###############################################################################
# Installation Details
###############################################################################
$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
@$(PREBUILD)
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar zxf $(DIR_DL)/$(DL_FILE)
cd $(DIR_APP) && mkdir build
cd $(DIR_APP)/build && cmake -D__LIB=lib -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_C_FLAGS="-O2" -DCMAKE_CXX_FLAGS="-O2" ..
cd $(DIR_APP)/build && make && make install
@rm -rf $(DIR_APP)
@$(POSTBUILD)

View File

@@ -83,6 +83,7 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
ln -svf vim /usr/bin/vi
install -m 644 $(DIR_SRC)/config/vim/vimrc /etc/vimrc
install -m 644 $(DIR_SRC)/config/vim/.vimrc /root/.vimrc
@rm -rf $(DIR_APP)
@$(POSTBUILD)

View File

@@ -68,7 +68,7 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
done
chown -R root:root /srv/web/ipfire
chmod -R 755 /srv/web/ipfire/cgi-bin
chmod -R 644 /srv/web/ipfire/html
#chmod -R 644 /srv/web/ipfire/html
chmod 755 /srv/web/ipfire/html /srv/web/ipfire/html/{index.cgi,redirect.cgi,images,include,themes,themes/*,themes/*/*}
# Reset permissions of redirect templates and theme directories

78
lfs/xdp-tools Normal file
View File

@@ -0,0 +1,78 @@
###############################################################################
# #
# IPFire.org - A linux based firewall #
# Copyright (C) 2007-2023 IPFire Team <info@ipfire.org> #
# Copyright (C) 2024 FireBeeOS
# #
# 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/>. #
# #
###############################################################################
###############################################################################
# Definitions
###############################################################################
include Config
VER = 1.4.2
THISAPP = xdp-tools-$(VER)
DL_FILE = $(THISAPP).tar.gz
DL_FROM = $(URL_IPFIRE)
DIR_APP = $(DIR_SRC)/$(THISAPP)
TARGET = $(DIR_INFO)/$(THISAPP)
###############################################################################
# Top-level Rules
###############################################################################
objects = $(DL_FILE)
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
$(DL_FILE)_BLAKE2 = 3dbf0f1de6a1d26a816c52b14861830d607178da160cc18aafe117412a1b2db99cc1e61b4577131ec0fc6f20cefa65a2bbc60712542f1d31707a31672f73728c
install : $(TARGET)
check : $(patsubst %,$(DIR_CHK)/%,$(objects))
download :$(patsubst %,$(DIR_DL)/%,$(objects))
b2 : $(subst %,%_BLAKE2,$(objects))
###############################################################################
# Downloading, checking, b2sum
###############################################################################
$(patsubst %,$(DIR_CHK)/%,$(objects)) :
@$(CHECK)
$(patsubst %,$(DIR_DL)/%,$(objects)) :
@$(LOAD)
$(subst %,%_BLAKE2,$(objects)) :
@$(B2SUM)
###############################################################################
# Installation Details
###############################################################################
$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
@$(PREBUILD)
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar zxf $(DIR_DL)/$(DL_FILE)
cd $(DIR_APP) && sed -i -e 's/PREFIX?=\/usr\/local/PREFIX?=\/usr/' lib/defines.mk
cd $(DIR_APP) && make && make install
@rm -rf $(DIR_APP)
@$(POSTBUILD)

17
make.sh
View File

@@ -444,10 +444,10 @@ prepareenv() {
if [ "${ENABLE_RAMDISK}" = "on" ]; then
mkdir -p $BASEDIR/build/usr/src
mount -t tmpfs tmpfs -o size=8G,nr_inodes=1M,mode=1777 $BASEDIR/build/usr/src
mount -t tmpfs tmpfs -o size=32G,nr_inodes=1M,mode=1777 $BASEDIR/build/usr/src
mkdir -p ${BASEDIR}/build/tmp
mount -t tmpfs tmpfs -o size=4G,nr_inodes=1M,mode=1777 ${BASEDIR}/build/tmp
mount -t tmpfs tmpfs -o size=16G,nr_inodes=1M,mode=1777 ${BASEDIR}/build/tmp
fi
mkdir -p $BASEDIR/build/usr/src/{cache,config,doc,html,langs,lfs,log,src,ccache}
@@ -1681,6 +1681,11 @@ buildipfire() {
lfsmake2 shairport-sync
lfsmake2 borgbackup
lfsmake2 lmdb
lfsmake2 pahole
lfsmake2 libbpf
lfsmake2 bpftool
lfsmake2 llvm-project
lfsmake2 xdp-tools
lfsmake2 knot
lfsmake2 spectre-meltdown-checker
lfsmake2 zabbix_agentd
@@ -1711,6 +1716,12 @@ buildipfire() {
lfsmake2 perl-URI-Encode
lfsmake2 rsnapshot
lfsmake2 mympd
lfsmake2 libmd
lfsmake2 libbsd
lfsmake2 loxilb-tc
lfsmake2 loxicmd
lfsmake2 loxilb
# Kernelbuild ... current we have no platform that need
# multi kernel builds so KCFG is empty
@@ -2031,6 +2042,7 @@ lang)
$BASEDIR/tools/sort_strings.pl nl
$BASEDIR/tools/sort_strings.pl tr
$BASEDIR/tools/sort_strings.pl it
$BASEDIR/tools/sort_strings.pl zh
$BASEDIR/tools/check_strings.pl en > $BASEDIR/doc/language_issues.en
$BASEDIR/tools/check_strings.pl de > $BASEDIR/doc/language_issues.de
$BASEDIR/tools/check_strings.pl fr > $BASEDIR/doc/language_issues.fr
@@ -2040,6 +2052,7 @@ lang)
$BASEDIR/tools/check_strings.pl nl > $BASEDIR/doc/language_issues.nl
$BASEDIR/tools/check_strings.pl tr > $BASEDIR/doc/language_issues.tr
$BASEDIR/tools/check_strings.pl it > $BASEDIR/doc/language_issues.it
$BASEDIR/tools/check_strings.pl zh > $BASEDIR/doc/language_issues.zh
$BASEDIR/tools/check_langs.sh > $BASEDIR/doc/language_missings
print_status DONE

View File

@@ -25515,6 +25515,7 @@ HCC 32 UK
HCC 33 US
HCC 34 Yugoslavia
HCC 35 Turkish-F
HCC 36 Chinese
# List of Video Class Terminal Types

View File

@@ -23,6 +23,7 @@
. ${rc_functions}
[ -r "/etc/sysconfig/keepalive" ] && . /etc/sysconfig/keepalive
eval $(/usr/local/bin/readhash /var/ipfire/keepalived/runsettings)
case "${1}" in
start)
@@ -32,8 +33,10 @@ case "${1}" in
# Enable connection tracking for IPVS
sysctl -w net.ipv4.vs.conntrack=1 &>/dev/null
boot_mesg "Starting keepalive daemon..."
loadproc /usr/sbin/keepalived ${KEEPALIVED_OPTIONS}
if [ "$ENABLE_HA" == "on" ]; then
boot_mesg "Starting keepalive daemon..."
loadproc /usr/sbin/keepalived ${KEEPALIVED_OPTIONS}
fi
;;
stop)

200
src/initscripts/system/ddos Executable file
View File

@@ -0,0 +1,200 @@
#!/bin/sh
###############################################################################
# #
# IPFire.org - A linux based firewall #
# Copyright (C) 2007-2022 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/>. #
# #
###############################################################################
. /etc/sysconfig/rc
. $rc_functions
eval $(/usr/local/bin/readhash /var/ipfire/ddos/settings)
eval $(/usr/local/bin/readhash /var/ipfire/ddos/udp-ddos-settings)
eval $(/usr/local/bin/readhash /var/ipfire/ddos/dns-ddos-settings)
get_ports () {
# Define an empty variable to store the output
local output=""
local ddos_port_file="$1"
# Read the input file line by line
while IFS= read -r line; do
# Check if the line contains '=on'
if [[ "$line" == [0-9]*"=on" ]]; then
# Extract the service/port number
service=$(echo "$line" | cut -d'=' -f1)
# Append the service/port number to the output string
output="$output$service,"
fi
done < $ddos_port_file
# Remove the trailing comma from the output string
output="${output%,}"
echo $output
}
load_syncookie () {
sysctl -w net.ipv4.tcp_syncookies=2
sysctl -w net.ipv4.tcp_timestamps=1
sysctl -w net.netfilter.nf_conntrack_tcp_loose=0
/usr/sbin/xdp-loader status red0 | grep 'syncookie_xdp'
if [ $? -eq 0 ]; then
prog_id=$(xdp-loader status red0 | grep 'syncookie_xdp' | awk '{print $4}')
xdp_synproxy --prog $prog_id --ports="$tcp_ports"
else
xdp-loader load red0 /usr/lib/bpf/xdp_synproxy.bpf.o
if [ $? -ge 1 ]; then
boot_mesg "Native mode not supported, try SKB"
xdp-loader load red0 -m skb /usr/lib/bpf/xdp_synproxy.bpf.o
prog_id=$(/usr/sbin/xdp-loader status red0 | grep 'syncookie_xdp' | awk '{print $4}')
xdp_synproxy --prog $prog_id --ports="$tcp_ports"
else
prog_id=$(/usr/sbin/xdp-loader status red0 | grep 'syncookie_xdp' | awk '{print $4}')
xdp_synproxy --prog $prog_id --ports="$tcp_ports"
fi
fi
}
load_xdpudp () {
/usr/sbin/xdp-loader status red0 | grep 'xdp_udp'
if [ $? -eq 0 ]; then
prog_id=$(xdp-loader status red0 | grep 'xdp_udp' | awk '{print $4}')
xdp-udp --prog $prog_id --ports="$udp_ports"
else
xdp-loader load red0 -P 90 -p /sys/fs/bpf/xdp-udp -n xdp_udp /usr/lib/bpf/xdp_udp.bpf.o
if [ $? -ge 1 ]; then
boot_mesg "Native mode not supported, try SKB"
xdp-loader load red0 -m skb -P 90 -p /sys/fs/bpf/xdp-udp -n xdp_udp /usr/lib/bpf/xdp_udp.bpf.o
prog_id=$(/usr/sbin/xdp-loader status red0 | grep 'xdp_udp' | awk '{print $4}')
xdp-udp --prog $prog_id --ports="$udp_ports"
else
prog_id=$(/usr/sbin/xdp-loader status red0 | grep 'xdp_udp' | awk '{print $4}')
xdp-udp --prog $prog_id --ports="$udp_ports"
fi
fi
}
load_xdpdns () {
/usr/sbin/xdp-loader status red0 | grep 'xdp_dns'
if [ $? -ne 0 ]; then
xdp-loader load red0 -P 80 -p /sys/fs/bpf/xdp-dns -n xdp_dns /usr/lib/bpf/xdp_dnsrrl.bpf.o
if [ $? -ge 1 ]; then
boot_mesg "Native mode not supported, try SKB"
xdp-loader load red0 -m skb -P 80 -p /sys/fs/bpf/xdp-dns -n xdp_dns /usr/lib/bpf/xdp_dnsrrl.bpf.o
fi
fi
}
unload_syncookie () {
sysctl -w net.ipv4.tcp_syncookies=1
/usr/sbin/xdp-loader status red0 | grep 'syncookie_xdp'
if [ $? -eq 0 ]; then
prog_id=$(xdp-loader status red0 | grep 'syncookie_xdp' | awk '{print $4}')
/usr/sbin/xdp-loader unload -i $prog_id red0
else
boot_mesg "Error syncookie_xdp not loaded!"
fi
}
unload_xdpudp () {
/usr/sbin/xdp-loader status red0 | grep 'xdp_udp'
if [ $? -eq 0 ]; then
prog_id=$(xdp-loader status red0 | grep 'xdp_udp' | awk '{print $4}')
/usr/sbin/xdp-loader unload -i $prog_id red0
/bin/rm -rf /sys/fs/bpf/xdp-udp
else
boot_mesg "Error xdp_udp not loaded!"
fi
}
unload_xdpdns () {
/usr/sbin/xdp-loader status red0 | grep 'xdp_dns'
if [ $? -eq 0 ]; then
prog_id=$(xdp-loader status red0 | grep 'xdp_dns' | awk '{print $4}')
/usr/sbin/xdp-loader unload -i $prog_id red0
/bin/rm -rf /sys/fs/bpf/xdp-dns
else
boot_mesg "Error xdp_dns not loaded!"
fi
}
set_ratelimit () {
local rate=$1
local map=$2
hex=$(printf '%08x' "$rate") # Convert decimal to hexadecimal
bytes=$(echo "$hex" | fold -w2 | tac) # Split the hexadecimal into pairs of bytes and reverse the order
hex_le=$(echo "$bytes" | sed 's/^/0x/' | tr '\n' ' ') # Add prefix "0x" to each byte and concatenate them
bpftool map update name $map key hex 00 00 00 00 value $hex_le
}
tcp_ports="$(get_ports /var/ipfire/ddos/settings)"
udp_ports="$(get_ports /var/ipfire/ddos/udp-ddos-settings)"
case "$1" in
start)
if [ ! -e /var/ipfire/red/active ]; then
boot_mesg " ERROR! Red0 interface not online!"
echo_warning
exit 1
fi
boot_mesg -n "Starting ddos..."
if [ "$ENABLE_DDOS" == "on" ]; then
load_syncookie
fi
if [ "$ENABLE_UDP_DDOS" == "on" ]; then
load_xdpudp
fi
if [ "$ENABLE_DNS_DDOS" == "on" ]; then
load_xdpdns
fi
;;
stop)
boot_mesg "Stopping ddos..."
if [ "$ENABLE_DDOS" == "off" ]; then
unload_syncookie
fi
if [ "$ENABLE_UDP_DDOS" == "off" ]; then
unload_xdpudp
if [ -n "$UDP_RATELIMIT" ]; then
set_ratelimit $UDP_RATELIMIT "xdp_udp.data"
fi
fi
if [ "$ENABLE_DNS_DDOS" == "off" ]; then
unload_xdpdns
if [ -n "$DNS_RATELIMIT" ]; then
set_ratelimit $DNS_RATELIMIT "xdp_dnsr.data"
fi
fi
;;
restart)
$0 stop
sleep 1
$0 start
;;
status)
/usr/sbin/xdp-loader status red0
;;
*)
echo "Usage: $0 {start|stop|restart|status}"
exit 1
;;
esac

View File

@@ -70,6 +70,12 @@ iptables_init() {
modprobe nf_log_ipv4
sysctl -q -w net.netfilter.nf_log.2=nf_log_ipv4
# XDP SYNPROXY Chain, needs to be first chain in INPUT as the chain order matters
iptables -t raw -N RAWSYNPROXY
iptables -t raw -A PREROUTING -j RAWSYNPROXY
iptables -N INSYNPROXY
iptables -A INPUT -j INSYNPROXY
# IPS Bypass Chain which stores the BYPASS bit in connection tracking
iptables -N IPSBYPASS
iptables -A IPSBYPASS -j CONNMARK --save-mark --mask "$(( ~IPS_REPEAT_MASK & 0xffffffff ))"

71
src/initscripts/system/loxilb Executable file
View File

@@ -0,0 +1,71 @@
#!/bin/sh
###############################################################################
# #
# IPFire.org - A linux based firewall #
# Copyright (C) 2007-2022 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/>. #
# #
###############################################################################
. /etc/sysconfig/rc
. $rc_functions
eval $(/usr/local/bin/readhash /var/ipfire/loxilb/settings)
case "$1" in
start)
boot_mesg -n "Starting loxilb..."
if [ "$ENABLE_LOXILB" == "on" ]; then
if [ -d /opt/loxilb/dp/ ]; then
umount /opt/loxilb/dp/
rm -fr /opt/loxilb/dp/bpf
fi
mkdir -p /opt/loxilb/dp/
mount -t bpf bpf /opt/loxilb/dp/
#enable egress firewall SNAT for green network
redip=$(< /var/ipfire/red/local-ipaddress)
sed -i "s/\"REDIP\"/\"$redip\"/" /var/ipfire/loxilb/FWconfig.txt
loadproc -b loxilb --config-path="/var/ipfire/loxilb/" --blacklist="eth[0-9]"
fi
;;
stop)
boot_mesg "Stopping loxilb..."
if [ "$ENABLE_LOXILB" == "off" ]; then
#remove egress firewall SNAT for green network
loxicmd delete firewall --firewallRule="portName:green0"
killproc loxilb
fi
;;
status)
statusproc /usr/bin/loxilb
;;
restart)
$0 stop
sleep 1
$0 start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
;;
esac

View File

@@ -46,6 +46,11 @@ case "${1}" in
mount -t cgroup2 none /sys/fs/cgroup || failed=1
fi
if ! mountpoint /sys/fs/bpf &> /dev/null; then
boot_mesg -n " /sys/fs/bpf" ${NORMAL}
mount -t bpf bpffs /sys/fs/bpf || failed=1
fi
if ! mountpoint /sys/firmware/efi/efivars &>/dev/null && [ -d "/sys/firmware/efi" ]; then
boot_mesg -n " /sys/firmware/efi/efivars" ${NORMAL}
mount -t efivarfs efivarfs /sys/firmware/efi/efivars || failed=1

View File

@@ -247,6 +247,7 @@ static char* center_string(const char* str, int width) {
#define DEFAULT_LANG "en.utf8"
#define NUM_LANGS 13
#define NUM_LANGS 14
static struct lang {
const char* code;
@@ -265,6 +266,7 @@ static struct lang {
{ "pt.utf8", "Portuguese (Brasil)" },
{ "ru.utf8", "Русский (Russian)" },
{ "tr.utf8", "Türkçe (Turkish)" },
{ "zh.utf8", "简体中文 (Chinese)" },
{ NULL, NULL },
};

View File

@@ -19,36 +19,36 @@ msgstr ""
#: main.c:78 main.c:179 main.c:404 main.c:670 main.c:702 main.c:893
msgid "OK"
msgstr ""
msgstr "确定"
#: main.c:79 main.c:460 main.c:487 main.c:516 main.c:620 main.c:630 main.c:670
#: main.c:702
msgid "Cancel"
msgstr ""
msgstr "取消"
#: main.c:176
msgid "I accept this license"
msgstr ""
msgstr "我接受此许可协议"
#: main.c:384
msgid "Warning: Unattended installation will start in 10 seconds..."
msgstr ""
msgstr "警告:无人值守安装将在 10 秒钟后开始..."
#: main.c:403
msgid "Language selection"
msgstr ""
msgstr "语言选择"
#: main.c:403
msgid "Select the language you wish to use for the installation."
msgstr ""
msgstr "请选择安装时要使用的语言。"
#: main.c:418
msgid "Unattended mode"
msgstr ""
msgstr "无人值守模式"
#: main.c:420
msgid "<Tab>/<Alt-Tab> between elements | <Space> selects | <F12> next screen"
msgstr ""
msgstr "<Tab>/<Alt-Tab> 切换元素 | <Space> 选择 | <F12> 下一屏幕"
#: main.c:426
#, c-format
@@ -57,15 +57,18 @@ msgid ""
"\n"
"Selecting Cancel on any of the following screens will reboot the computer."
msgstr ""
"欢迎使用 %s 安装程序。\n"
"\n"
"在以下任何屏幕上选择取消将重新启动计算机。"
#: main.c:428
msgid "Start installation"
msgstr ""
msgstr "开始安装"
#: main.c:449
#, c-format
msgid "The installer will now try downloading the installation image."
msgstr ""
msgstr "安装程序现在将尝试下载安装镜像。"
#: main.c:452
#, c-format
@@ -74,20 +77,24 @@ msgid ""
"\n"
"You can try downloading the required installation image."
msgstr ""
"找不到源驱动器。\n"
"\n"
"您可以尝试下载所需的安装镜像。"
#: main.c:456
msgid ""
"Please make sure to connect your machine to a network and the installer will"
" try connect to acquire an IP address."
msgstr ""
"请确保将您的机器连接到网络,安装程序将尝试连接以获取 IP 地址。"
#: main.c:460
msgid "Download installation image"
msgstr ""
msgstr "下载安装镜像"
#: main.c:473
msgid "Trying to start networking (DHCP)..."
msgstr ""
msgstr "正在尝试启动网络DHCP..."
#: main.c:484
msgid ""
@@ -95,19 +102,22 @@ msgid ""
"\n"
"Please connect your machine to a network with a DHCP server and retry."
msgstr ""
"无法启动网络,但是安装继续进行需要网络支持。\n"
"\n"
"请将您的机器连接到一个带有 DHCP 服务器的网络,然后重试。"
#: main.c:487 main.c:516
msgid "Retry"
msgstr ""
msgstr "重试"
#: main.c:501
msgid "Downloading installation image..."
msgstr ""
msgstr "正在下载安装镜像..."
#: main.c:510
#, c-format
msgid "BLAKE2 checksum mismatch"
msgstr ""
msgid "MD5 checksum mismatch"
msgstr "MD5 校验和不匹配"
#: main.c:513
#, c-format
@@ -117,6 +127,10 @@ msgid ""
"\n"
"%s"
msgstr ""
"无法下载安装镜像。\n"
" 原因:%s\n"
"\n"
"%s"
#: main.c:528
#, c-format
@@ -124,22 +138,24 @@ msgid ""
"Could not mount %s to %s:\n"
" %s\n"
msgstr ""
"无法挂载 %s 到 %s\n"
" %s\n"
#: main.c:543
msgid "License Agreement"
msgstr ""
msgstr "许可协议"
#: main.c:544
msgid "License not accepted!"
msgstr ""
msgstr "未接受许可协议!"
#: main.c:566
msgid "No hard disk found."
msgstr ""
msgstr "找不到硬盘。"
#: main.c:587
msgid "Disk Selection"
msgstr ""
msgstr "选择硬盘"
#: main.c:588
msgid ""
@@ -147,6 +163,9 @@ msgid ""
"\n"
"ALL DATA ON THE DISK WILL BE DESTROYED."
msgstr ""
"请选择要安装 IPFire 的硬盘。首先将对其进行分区,然后在分区上创建文件系统。\n"
"\n"
"硬盘上的所有数据将被删除。"
#: main.c:599
msgid ""
@@ -154,6 +173,9 @@ msgid ""
"\n"
"Please select one or more disks you want to install IPFire on."
msgstr ""
"未选择任何硬盘。\n"
"\n"
"请选择要安装 IPFire 的一个或多个硬盘。"
#: main.c:617
#, c-format
@@ -164,14 +186,19 @@ msgid ""
"\n"
"Do you agree to continue?"
msgstr ""
"安装程序将准备所选的硬盘:\n"
"\n"
" %s\n"
"\n"
"您同意继续吗?"
#: main.c:619
msgid "Disk Setup"
msgstr ""
msgstr "硬盘设置"
#: main.c:620 main.c:630
msgid "Delete all data"
msgstr ""
msgstr "删除所有数据"
#: main.c:627
#, c-format
@@ -183,103 +210,110 @@ msgid ""
"\n"
"Do you agree to continue?"
msgstr ""
"安装程序将在选定的硬盘上设置 RAID 配置:\n"
"\n"
" %s\n"
" %s\n"
"\n"
"您同意继续吗?"
#: main.c:629
msgid "RAID Setup"
msgstr ""
msgstr "RAID 设置"
#: main.c:640
msgid "Your disk configuration is currently not supported."
msgstr ""
msgstr "当前不支持您的硬盘配置。"
#: main.c:655
msgid "Your harddisk is too small."
msgstr ""
msgstr "您的硬盘太小了。"
#: main.c:671
msgid ""
"Your harddisk is very small, but you can continue without a swap partition."
msgstr ""
"您的硬盘非常小,但是您可以继续安装而不创建交换分区。"
#: main.c:684
msgid "ext4 Filesystem"
msgstr ""
msgstr "ext4 文件系统"
#: main.c:685
msgid "ext4 Filesystem without journal"
msgstr ""
msgstr "不带日志的 ext4 文件系统"
#: main.c:686
msgid "XFS Filesystem"
msgstr ""
msgstr "XFS 文件系统"
#: main.c:687
msgid "ReiserFS Filesystem"
msgstr ""
msgstr "ReiserFS 文件系统"
#: main.c:701
msgid "Filesystem Selection"
msgstr ""
msgstr "文件系统选择"
#: main.c:701
msgid "Please choose your filesystem:"
msgstr ""
msgstr "请选择您的文件系统:"
#: main.c:712
msgid "Building RAID..."
msgstr ""
msgstr "正在构建 RAID..."
#: main.c:716
msgid "Unable to build the RAID."
msgstr ""
msgstr "无法构建 RAID。"
#: main.c:728
msgid "Partitioning disk..."
msgstr ""
msgstr "正在分区硬盘..."
#: main.c:732
msgid "Unable to partition the disk."
msgstr ""
msgstr "无法对硬盘进行分区。"
#: main.c:739
msgid "Creating filesystems..."
msgstr ""
msgstr "正在创建文件系统..."
#: main.c:743
msgid "Unable to create filesystems."
msgstr ""
msgstr "无法创建文件系统。"
#: main.c:749
msgid "Unable to mount filesystems."
msgstr ""
msgstr "无法挂载文件系统。"
#: main.c:760
msgid "Installing the system..."
msgstr ""
msgstr "正在安装系统..."
#: main.c:761
msgid "Unable to install the system."
msgstr ""
msgstr "无法安装系统。"
#: main.c:777
msgid "Installing the language cache..."
msgstr ""
msgstr "正在安装语言缓存..."
#: main.c:778
msgid "Unable to install the language cache."
msgstr ""
msgstr "无法安装语言缓存。"
#: main.c:783
msgid "Installing the bootloader..."
msgstr ""
msgstr "正在安装引导程序..."
#: main.c:790
msgid "Unable to open /etc/default/grub for writing."
msgstr ""
msgstr "无法打开 /etc/default/grub 进行写入。"
#: main.c:812
msgid "Unable to install the bootloader."
msgstr ""
msgstr "无法安装引导程序。"
#: main.c:826
msgid ""
@@ -287,26 +321,29 @@ msgid ""
"\n"
"Do you want to restore the backup?"
msgstr ""
"在安装映像上找到了一个备份文件。\n"
"\n"
"您要恢复备份吗?"
#: main.c:827
msgid "Yes"
msgstr ""
msgstr ""
#: main.c:827
msgid "No"
msgstr ""
msgstr ""
#: main.c:834
msgid "An error occured when the backup file was restored."
msgstr ""
msgstr "恢复备份文件时发生错误。"
#: main.c:869
msgid "Running post-install script..."
msgstr ""
msgstr "正在运行安装后脚本..."
#: main.c:870
msgid "Post-install script failed."
msgstr ""
msgstr "安装后脚本执行失败。"
#: main.c:877
#, c-format
@@ -315,15 +352,18 @@ msgid ""
"\n"
"Please remove any installation mediums from this system and hit the reboot button. Once the system has restarted you will be asked to setup networking and system passwords. After that, you should point your web browser at https://%s:444 (or what ever you name your %s) for the web configuration console."
msgstr ""
"%s 安装成功!\n"
"\n"
"请从系统中移除任何安装介质并点击重新启动按钮。系统重新启动后,您将被要求设置网络和系统密码。完成后,您可以在您命名的 %s 上通过 https://%s:444 进入 Web 配置控制台。"
#: main.c:882
msgid "Congratulations!"
msgstr ""
msgstr "恭喜您!"
#: main.c:882
msgid "Reboot"
msgstr ""
msgstr "重新启动"
#: main.c:893
msgid "Setup has failed. Press Ok to reboot."
msgstr ""
msgstr "安装失败。按下“确定”重新启动。"

View File

@@ -32,7 +32,7 @@ SUID_PROGS = squidctrl sshctrl ipfirereboot \
smartctrl clamavctrl addonctrl pakfire mpfirectrl wlanapctrl \
setaliases urlfilterctrl updxlratorctrl fireinfoctrl rebuildroutes \
getconntracktable wirelessclient torctrl ddnsctrl unboundctrl \
captivectrl
captivectrl ddosctrl loxilbctrl keepalivedctrl
OBJS = $(patsubst %,%.o,$(PROGS) $(SUID_PROGS))

40
src/misc-progs/ddosctrl.c Normal file
View File

@@ -0,0 +1,40 @@
/* This file is part of the IPFire Firewall.
*
* This program is distributed under the terms of the GNU General Public
* Licence. See the file COPYING for details.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include "setuid.h"
int main(int argc, char *argv[]) {
if (!(initsetuid()))
exit(1);
if (argc < 2) {
fprintf(stderr, "\nNo argument given.\n\nddosctrl (start|stop|restart)\n\n");
exit(1);
}
if (strcmp(argv[1], "start") == 0) {
safe_system("/etc/rc.d/init.d/ddos start");
} else if (strcmp(argv[1], "stop") == 0) {
safe_system("/etc/rc.d/init.d/ddos stop");
} else if (strcmp(argv[1], "restart") == 0) {
safe_system("/etc/rc.d/init.d/ddos restart");
} else if (strcmp(argv[1], "status") == 0) {
safe_system("/etc/rc.d/init.d/ddos status");
} else {
fprintf(stderr, "\nBad argument given.\n\nddosctrl (start|stop|restart|status)\n\n");
exit(1);
}
return 0;
}

View File

@@ -0,0 +1,40 @@
/* This file is part of the IPFire Firewall.
*
* This program is distributed under the terms of the GNU General Public
* Licence. See the file COPYING for details.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include "setuid.h"
int main(int argc, char *argv[]) {
if (!(initsetuid()))
exit(1);
if (argc < 2) {
fprintf(stderr, "\nNo argument given.\n\nkeepalivedctrl (start|stop|restart)\n\n");
exit(1);
}
if (strcmp(argv[1], "start") == 0) {
safe_system("/etc/rc.d/init.d/keepalived start");
} else if (strcmp(argv[1], "stop") == 0) {
safe_system("/etc/rc.d/init.d/keepalived stop");
} else if (strcmp(argv[1], "status") == 0) {
safe_system("/etc/rc.d/init.d/keepalived status");
} else if (strcmp(argv[1], "restart") == 0) {
safe_system("/etc/rc.d/init.d/keepalived restart");
} else {
fprintf(stderr, "\nBad argument given.\n\nkeepalivedctrl (start|stop|restart)\n\n");
exit(1);
}
return 0;
}

View File

@@ -0,0 +1,40 @@
/* This file is part of the IPFire Firewall.
*
* This program is distributed under the terms of the GNU General Public
* Licence. See the file COPYING for details.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include "setuid.h"
int main(int argc, char *argv[]) {
if (!(initsetuid()))
exit(1);
if (argc < 2) {
fprintf(stderr, "\nNo argument given.\n\nloxilbctrl (start|stop|restart)\n\n");
exit(1);
}
if (strcmp(argv[1], "start") == 0) {
safe_system("/etc/rc.d/init.d/loxilb start");
} else if (strcmp(argv[1], "stop") == 0) {
safe_system("/etc/rc.d/init.d/loxilb stop");
} else if (strcmp(argv[1], "status") == 0) {
safe_system("/etc/rc.d/init.d/loxilb status");
} else if (strcmp(argv[1], "restart") == 0) {
safe_system("/etc/rc.d/init.d/loxilb restart");
} else {
fprintf(stderr, "\nBad argument given.\n\nloxilbctrl (start|stop|restart)\n\n");
exit(1);
}
return 0;
}

View File

@@ -4,6 +4,7 @@
#
# Translators:
# ipfire <qiwenqiu@yahoo.com.hk>, 2015
# bpfire <vincent.mc.li@gmail.com>, 2024
msgid ""
msgstr ""
"Project-Id-Version: IPFire Project\n"
@@ -12,6 +13,8 @@ msgstr ""
"PO-Revision-Date: 2017-09-20 09:45+0000\n"
"Last-Translator: ipfire <qiwenqiu@yahoo.com.hk>\n"
"Language-Team: Chinese (http://www.transifex.com/mstremer/ipfire/language/zh/)\n"
"PO-Revision-Date: 2024-07-228 06:45+0000\n"
"Last-Translator: bpfire <vincent.mc.li@gmail.com>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -84,355 +87,356 @@ msgstr "取消"
#: dhcp.c:156
msgid ""
"The following fields are invalid:\n"
"\n"
msgstr ""
"以下填空字段无效:\n"
#: dhcp.c:159
msgid "Start address"
msgstr ""
msgstr "起始地址"
#: dhcp.c:165
msgid "End address"
msgstr ""
msgstr "结束地址"
#: dhcp.c:173 networking.c:755
msgid "Primary DNS"
msgstr ""
msgstr "主域名服务器"
#: dhcp.c:182 networking.c:764
msgid "Secondary DNS"
msgstr ""
msgstr "备域名服务器"
#: dhcp.c:189
msgid "Default lease time"
msgstr ""
msgstr "默认租用时间"
#: dhcp.c:195
msgid "Max. lease time"
msgstr ""
msgstr "最长租用时间"
#: domainname.c:42 main.c:70
msgid "Domain name"
msgstr ""
msgstr "域名"
#: domainname.c:42
msgid "Enter Domain name"
msgstr ""
msgstr "输入域名"
#: domainname.c:48
msgid "Domain name cannot be empty."
msgstr ""
msgstr "域名不能为空。"
#: domainname.c:50
msgid "Domain name cannot contain spaces."
msgstr ""
msgstr "域名不能包含空格。"
#: domainname.c:53
msgid "Domain name may only contain letters, numbers, hyphens and periods."
msgstr ""
msgstr "域名只能包含字母、数字、连字符和句点。"
#: hostname.c:46 main.c:69
msgid "Hostname"
msgstr ""
msgstr "主机名"
#: hostname.c:46
msgid "Enter the machine's hostname."
msgstr ""
msgstr "输入主机的主机名。"
#: hostname.c:53
msgid "Hostname cannot be empty."
msgstr ""
msgstr "主机名不能为空。"
#: hostname.c:55
msgid "Hostname cannot contain spaces."
msgstr ""
msgstr "主机名不能包含空格。"
#: hostname.c:58
msgid "Hostname may only contain letters, numbers and hyphens."
msgstr ""
msgstr "主机名只能包含字母、数字和连字符。"
#: keymap.c:84 main.c:67
msgid "Keyboard mapping"
msgstr ""
msgstr "键盘映射"
#: keymap.c:85
msgid "Choose the type of keyboard you are using from the list below."
msgstr ""
msgstr "从下面的列表中选择您正在使用的键盘类型。"
#: main.c:68 timezone.c:77
msgid "Timezone"
msgstr ""
msgstr "时区"
#: main.c:71 networking.c:110 networking.c:115 networking.c:447
msgid "Networking"
msgstr ""
msgstr "网络设置"
#: main.c:72 misc.c:147
msgid "ISDN"
msgstr ""
msgstr "ISDN"
#: main.c:73
msgid "'root' password"
msgstr ""
msgstr "root 密码"
#: main.c:74
msgid "'admin' password"
msgstr ""
msgstr "admin 密码"
#: main.c:90
msgid " <Tab>/<Alt-Tab> between elements | <Space> selects"
msgstr ""
msgstr " <Tab>/<Alt-Tab> 在元素间切换 | <Space> 选择"
#: main.c:97
msgid "Section menu"
msgstr ""
msgstr "部分菜单"
#: main.c:98
msgid "Select the item you wish to configure."
msgstr ""
msgstr "选择您希望配置的项目。"
#: main.c:99
msgid "Quit"
msgstr ""
msgstr "退出"
#: main.c:172
msgid "Setup is complete."
msgstr ""
msgstr "设置已完成。"
#: main.c:174 netstuff.c:733 networking.c:560 networking.c:653
msgid "Warning"
msgstr ""
msgstr "警告"
#: main.c:175
msgid ""
"Initial setup was not entirely complete. You must ensure that Setup is "
"properly finished by running setup again at the shell."
msgstr ""
"初始setup并未完全完成。您必须确保通过在shell中再次运行setup来正确完成设置。"
#: misc.c:62
#, c-format
msgid "Unable to write %s/main/hostname.conf"
msgstr ""
msgstr "无法写入 %s/main/hostname.conf"
#: misc.c:71
msgid "Unable to open main hosts file."
msgstr ""
msgstr "无法打开主机文件。"
#: misc.c:76
msgid "Unable to write /etc/hosts."
msgstr ""
msgstr "无法写入 /etc/hosts。"
#: misc.c:117
msgid "Unable to write /etc/hosts.deny."
msgstr ""
msgstr "无法写入 /etc/hosts.deny。"
#: misc.c:125
msgid "Unable to write /etc/hosts.allow."
msgstr ""
msgstr "无法写入 /etc/hosts.allow。"
#: misc.c:136
msgid "Unable to set hostname."
msgstr ""
msgstr "无法设置主机名。"
#: misc.c:147
msgid "Scanning and configuring ISDN devices."
msgstr ""
msgstr "正在扫描和配置ISDN设备。"
#: misc.c:148
msgid "Unable to scan for ISDN devices."
msgstr ""
msgstr "无法扫描ISDN设备。"
#: netstuff.c:86
#, c-format
msgid "Interface - %s"
msgstr ""
msgstr "接口 - %s"
#: netstuff.c:91
#, c-format
msgid "Enter the IP address information for the %s interface."
msgstr ""
msgstr "为 %s 接口输入IP地址信息。"
#: netstuff.c:103
msgid "Static"
msgstr ""
msgstr "静态"
#: netstuff.c:104
msgid "DHCP"
msgstr ""
msgstr "DHCP"
#: netstuff.c:105
msgid "PPP DIALUP (PPPoE, modem, ATM ...)"
msgstr ""
msgstr "PPP拨号连接PPPoE调制解调器ATM ..."
#: netstuff.c:113
msgid "DHCP Hostname:"
msgstr ""
msgstr "DHCP主机名"
#: netstuff.c:115
msgid "Force DHCP MTU:"
msgstr ""
msgstr "强制DHCP MTU"
#: netstuff.c:134
msgid "IP address:"
msgstr ""
msgstr "IP地址"
#: netstuff.c:146
msgid "Network mask:"
msgstr ""
msgstr "子网掩码:"
#: netstuff.c:173 networking.c:749
msgid "The following fields are invalid:"
msgstr ""
msgstr "以下字段无效:"
#: netstuff.c:183
msgid "IP address"
msgstr ""
msgstr "IP地址"
#: netstuff.c:189
msgid "Network mask"
msgstr ""
msgstr "子网掩码"
#: netstuff.c:198
msgid "DHCP hostname"
msgstr ""
msgstr "DHCP主机名"
#: netstuff.c:396 netstuff.c:709
msgid "Unset"
msgstr ""
msgstr "未设置"
#: netstuff.c:669
#, c-format
msgid "Please choose a networkcard for the following interface - %s."
msgstr ""
msgid "Please choose a network card for the following interface - %s."
msgstr "请选择以下接口的网络卡 - %s。"
#: netstuff.c:672
msgid "Extended Network Menu"
msgstr ""
msgstr "扩展网络菜单"
#: netstuff.c:673 networking.c:520
msgid "Select"
msgstr ""
msgstr "选择"
#: netstuff.c:673
msgid "Identify"
msgstr ""
msgstr "识别"
#: netstuff.c:678
msgid "Device Identification"
msgstr ""
msgstr "设备识别"
#: netstuff.c:678
msgid "The lights on the selected port should flash now for 10 seconds..."
msgstr ""
msgstr "选定端口上的指示灯应该现在闪烁10秒钟..."
#: netstuff.c:679
msgid "Identification is not supported by this interface."
msgstr ""
msgstr "此接口不支持识别功能。"
#: netstuff.c:691
msgid "There are no unassigned interfaces on your system."
msgstr ""
msgstr "系统中没有未分配的接口。"
#: netstuff.c:732
#, c-format
msgid "Do you really want to remove the assigned %s interface?"
msgstr ""
msgstr "您确定要移除分配的 %s 接口吗?"
#: netstuff.c:755
msgid "Select network driver"
msgstr ""
msgstr "选择网络驱动程序"
#: netstuff.c:755
msgid "Set additional module parameters"
msgstr ""
msgstr "设置额外的模块参数"
#: netstuff.c:762
msgid "Loading module..."
msgstr ""
msgstr "正在加载模块..."
#: netstuff.c:777
msgid "Unable to load driver module."
msgstr ""
msgstr "无法加载驱动模块。"
#: netstuff.c:780
msgid "Module name cannot be blank."
msgstr ""
msgstr "模块名称不能为空。"
#: networking.c:110
msgid "Stopping network..."
msgstr ""
msgstr "停止网络..."
#: networking.c:115
msgid "Restarting network..."
msgstr ""
msgstr "重启网络..."
#: networking.c:146
msgid "No GREEN interface assigned."
msgstr ""
msgstr "未分配 GREEN 接口。"
#: networking.c:152
msgid "Missing an IP address on GREEN."
msgstr ""
msgstr "GREEN 上缺少IP地址。"
#: networking.c:163
msgid "Error"
msgstr ""
msgstr "错误"
#: networking.c:163
msgid "Ignore"
msgstr ""
msgstr "忽略"
#: networking.c:164
msgid "No RED interface assigned."
msgstr ""
msgstr "未分配 RED 接口。"
#: networking.c:173
msgid "Missing an IP address on RED."
msgstr ""
msgstr "RED 上缺少IP地址。"
#: networking.c:183
msgid "No ORANGE interface assigned."
msgstr ""
msgstr "未分配 ORANGE 接口。"
#: networking.c:189
msgid "Missing an IP address on ORANGE."
msgstr ""
msgstr "ORANGE 上缺少IP地址。"
#: networking.c:199
msgid "No BLUE interface assigned."
msgstr ""
msgstr "未分配 BLUE 接口。"
#: networking.c:205
msgid "Missing an IP address on BLUE."
msgstr ""
msgstr "BLUE 上缺少IP地址。"
#: networking.c:217
msgid "Misssing DNS."
msgstr ""
msgid "Missing DNS."
msgstr "缺少DNS。"
#: networking.c:224
msgid "Missing Default Gateway."
msgstr ""
msgstr "缺少默认网关。"
#: networking.c:237 networking.c:304
msgid "Network configuration type"
msgstr ""
msgstr "网络配置类型"
#: networking.c:238 networking.c:409
msgid "Drivers and card assignments"
msgstr ""
msgstr "驱动程序和网卡分配"
#: networking.c:239 networking.c:640
msgid "Address settings"
msgstr ""
msgstr "地址设置"
#: networking.c:240 networking.c:743
msgid "DNS and Gateway settings"
msgstr ""
msgstr "DNS和网关设置"
#: networking.c:260
msgid "When configuration is complete, a network restart will be required."
msgstr ""
msgstr "配置完成后,需要重新启动网络。"
#: networking.c:267
#, c-format
@@ -441,14 +445,17 @@ msgid ""
"\n"
"%s"
msgstr ""
"当前配置:%s\n"
"\n"
"%s"
#: networking.c:268
msgid "Network configuration menu"
msgstr ""
msgstr "网络配置菜单"
#: networking.c:269 networking.c:520 networking.c:642
msgid "Done"
msgstr ""
msgstr "完成"
#: networking.c:300
#, c-format
@@ -458,6 +465,7 @@ msgid ""
"setting, a network restart will be required, and you will have to "
"reconfigure the network driver assignments."
msgstr ""
"选择 %s 的网络配置。以下配置类型列出了已连接以太网的接口。如果更改此设置,将需要重新启动网络,并且您将需要重新配置网络驱动程序分配。"
#: networking.c:307
#, c-format
@@ -466,34 +474,41 @@ msgid ""
"\n"
"Needed: %d - Available: %d\n"
msgstr ""
"没有足够的网卡供您选择。\n"
"\n"
"所需:%d - 可用:%d\n"
#: networking.c:359
msgid ""
"Configure network drivers, and which interface each card is assigned to. The current configuration is as follows:\n"
"\n"
msgstr ""
"配置网络驱动程序及每张网卡分配的接口。当前配置如下:\n"
"\n"
#: networking.c:408
msgid "Do you wish to change these settings?"
msgstr ""
msgstr "您是否希望更改这些设置?"
#: networking.c:447
msgid "Restarting non-local network..."
msgstr ""
msgstr "正在重新启动非本地网络..."
#: networking.c:464
msgid ""
"Please choose the interface you wish to change.\n"
"\n"
msgstr ""
"请选择您希望更改的接口。\n"
"\n"
#: networking.c:519
msgid "Assigned Cards"
msgstr ""
msgstr "已分配的网卡"
#: networking.c:520
msgid "Remove"
msgstr ""
msgstr "移除"
#: networking.c:556 networking.c:649
#, c-format
@@ -503,45 +518,48 @@ msgid ""
"on the new IP. This is a risky operation, and should only be attempted if "
"you have physical access to the machine, should something go wrong."
msgstr ""
"如果您更改此IP地址并且您是远程登录的您将会断开与 %s 机器的连接您需要在新IP上重新连接。这是一项风险较高的操作只有在您有机器的物理访问权限时才应尝试执行以防出现问题。"
#: networking.c:641
msgid "Select the interface you wish to reconfigure."
msgstr ""
msgstr "选择您希望重新配置的接口。"
#: networking.c:729
msgid "Default gateway:"
msgstr ""
msgstr "默认网关:"
#: networking.c:744
msgid ""
"Enter the DNS and gateway information. These settings are used only with "
"Static IP (and DHCP if DNS set) on the RED interface."
msgstr ""
"输入DNS和网关信息。这些设置仅用于RED接口上的静态IP以及如果设置了DNS的话DHCP也适用。"
#: networking.c:773
msgid "Default gateway"
msgstr ""
msgstr "默认网关"
#: networking.c:780
msgid "Secondary DNS specified without a Primary DNS"
msgstr ""
msgstr "指定了次要DNS但未指定主要DNS"
#: passwords.c:33
msgid ""
"Enter the 'root' user password. Login as this user for commandline access."
msgstr ""
"输入 'root' 用户密码。以此用户登录以获取命令行访问权限。"
#: passwords.c:38 passwords.c:61
msgid "Setting password"
msgstr ""
msgstr "设置密码"
#: passwords.c:38
msgid "Setting 'root' password...."
msgstr ""
msgstr "正在设置 'root' 密码...."
#: passwords.c:39
msgid "Problem setting 'root' password."
msgstr ""
msgstr "设置 'root' 密码时出现问题。"
#: passwords.c:53
#, c-format
@@ -549,37 +567,38 @@ msgid ""
"Enter %s 'admin' user password. This is the user to use for logging into the"
" %s web administration pages."
msgstr ""
"输入 %s 'admin' 用户密码。此用户用于登录到 %s 网页管理页面。"
#: passwords.c:60
#, c-format
msgid "Setting %s 'admin' user password..."
msgstr ""
msgstr "正在设置 %s 'admin' 用户密码..."
#: passwords.c:62
#, c-format
msgid "Problem setting %s 'admin' user password."
msgstr ""
msgstr "设置 %s 'admin' 用户密码时出现问题。"
#: passwords.c:76
msgid "Password:"
msgstr ""
msgstr "密码:"
#: passwords.c:77
msgid "Again:"
msgstr ""
msgstr "再次输入:"
#: passwords.c:95
msgid "Password cannot be blank."
msgstr ""
msgstr "密码不能为空。"
#: passwords.c:102
msgid "Passwords do not match."
msgstr ""
msgstr "密码不匹配。"
#: passwords.c:109
msgid "Password cannot contain spaces."
msgstr ""
msgstr "密码不能包含空格。"
#: timezone.c:77
msgid "Choose the timezone you are in from the list below."
msgstr ""
msgstr "从下面的列表中选择您所在的时区。"