Files
2026-10-29 18:46:39 +08:00

194 lines
5.6 KiB
Bash
Executable File

#!/bin/sh /etc/rc.common
# Copyright (C) 2021-2025 Lienol <lawlienol@gmail.com>
START=99
STOP=10
USE_PROCD=1
PROG=/usr/sbin/openvpn
CONFIG="luci-app-openvpn-server"
OVPN_PATH=/usr/share/openvpn-server
TMP_OVPN_PATH=/var/etc/openvpn-server
port=$(uci -q get ${CONFIG}.server.port || echo "1194")
proto=$(uci -q get ${CONFIG}.server.proto || echo "udp")
ip_segment=$(uci -q get ${CONFIG}.server.ip_segment || echo "172.30.1.0")
subnet_mask=$(uci -q get ${CONFIG}.server.subnet_mask || echo "255.255.255.0")
ipv6=$(uci -q get ${CONFIG}.server.ipv6 || echo "0")
[ "${ipv6}" -eq 1 ] && [ -z "$(command -v ip6tables)" ] && ipv6=0
ip_prefix="$(ipcalc.sh ${ip_segment} ${subnet_mask} | grep "PREFIX" | awk -F '=' '{print $2}')"
ipt_flag="OpenVPN Server"
ipt_rule() {
if [ "$1" = "add" ]; then
iptables -w -t nat -I POSTROUTING -s ${ip_segment%.*}.0/${ip_prefix} -m comment --comment "${ipt_flag}" -j MASQUERADE 2>/dev/null
iptables -w -I FORWARD -s ${ip_segment%.*}.0/${ip_prefix} -m comment --comment "${ipt_flag}" -j ACCEPT 2>/dev/null
iptables -w -I INPUT -p ${proto} --dport ${port} -m comment --comment "${ipt_flag}" -j ACCEPT 2>/dev/null
iptables -w -t mangle -I OUTPUT -p ${proto} --sport ${port} -m comment --comment "${ipt_flag}" -j RETURN 2>/dev/null
[ "${ipv6}" -eq 1 ] && {
ip6tables -w -I INPUT -p ${proto} --dport ${port} -m comment --comment "${ipt_flag}" -j ACCEPT 2>/dev/null
ip6tables -w -t mangle -I OUTPUT -p ${proto} --sport ${port} -m comment --comment "${ipt_flag}" -j RETURN 2>/dev/null
}
else
ipt_del() {
for i in $(seq 1 $($1 -nL $2 | grep -c "${ipt_flag}")); do
local index=$($1 --line-number -nL $2 | grep "${ipt_flag}" | head -1 | awk '{print $1}')
$1 -w -D $2 $index 2>/dev/null
done
}
ipt_del "iptables" "FORWARD"
ipt_del "iptables" "INPUT"
ipt_del "iptables -t nat" "POSTROUTING"
ipt_del "iptables -t mangle" "OUTPUT"
ipt_del "ip6tables" "INPUT"
ipt_del "ip6tables -t mangle" "OUTPUT"
fi
}
gen_include() {
echo '#!/bin/sh' > /var/etc/${CONFIG}.include
extract_rules() {
local _ipt="iptables"
[ "$1" == "6" ] && _ipt="ip6tables"
echo "*$2"
${_ipt}-save -t $2 | grep "${ipt_flag}" | sed -e "s#\-A#\-I#g"
echo 'COMMIT'
}
cat <<-EOF >> /var/etc/${CONFIG}.include
iptables-save -c | grep -v "${ipt_flag}" | iptables-restore -w -c
iptables-restore -w -n <<-EOT
$(extract_rules 4 filter)
$(extract_rules 4 nat)
$(extract_rules 4 mangle)
EOT
[ "${ipv6}" -eq 1 ] && {
ip6tables-save -c | grep -v "${ipt_flag}" | ip6tables-restore -w -c
ip6tables-restore -w -n <<-EOT
$(extract_rules 6 filter)
$(extract_rules 6 mangle)
EOT
}
exit 0
EOF
return 0
}
start_service() {
local enabled=$(uci -q get ${CONFIG}.server.enabled)
[ "${enabled}" -eq 1 ] || return 1
mkdir -p ${TMP_OVPN_PATH}
_ca=${OVPN_PATH}/ca.crt
_cert=${OVPN_PATH}/server.crt
_key=${OVPN_PATH}/server.key
_dh=${OVPN_PATH}/dh.pem
mkdir -p ${TMP_OVPN_PATH}/ccd
_auth_path=${TMP_OVPN_PATH}/auth
touch ${_auth_path}
local _users=$(uci -q show ${CONFIG} | grep "=users" | cut -d '.' -sf2 | cut -d '=' -sf 1)
[ -n "${_users}" ] && {
for _user in ${_users}; do
local u_enabled=$(uci -q get ${CONFIG}.${_user}.enabled)
[ "${u_enabled}" -eq 1 ] || continue
local u_username=$(uci -q get ${CONFIG}.${_user}.username)
[ -n "${u_username}" ] || continue
local u_password=$(uci -q get ${CONFIG}.${_user}.password)
[ -n "${u_password}" ] || continue
echo "${u_username} ${u_password}" >> ${_auth_path}
local u_ipaddress=$(uci -q get ${CONFIG}.${_user}.ipaddress)
[ -n "${u_ipaddress}" ] && echo "ifconfig-push ${u_ipaddress} ${subnet_mask}" >> ${TMP_OVPN_PATH}/ccd/${u_username}
local u_routes=$(uci -q get ${CONFIG}.${_user}.routes)
for u_route in ${u_routes}; do
eval "$(ipcalc.sh ${u_route})"
echo "iroute ${IP} ${NETMASK}" >> ${TMP_OVPN_PATH}/ccd/${u_username}
done
unset u_enabled u_username u_password u_ipaddress u_routes
done
}
SCRIPT_PATH=${OVPN_PATH}/script
chmod 0755 ${SCRIPT_PATH}/*
local extra_config=$(uci -q get ${CONFIG}.server.extra_config)
cat <<-EOF >> ${TMP_OVPN_PATH}/server.conf
management 127.0.0.1 17777
port ${port}
proto ${proto}$([ "${ipv6}" -eq 1 ] && echo "6")
dev ovpn_server
dev-type tun
ca ${_ca}
cert ${_cert}
key ${_key}
dh ${_dh}
topology subnet
auth-user-pass-verify ${SCRIPT_PATH}/auth_verify.sh via-env
verify-client-cert none
username-as-common-name
client-config-dir ${TMP_OVPN_PATH}/ccd
server ${ip_segment} ${subnet_mask}
ifconfig-pool-persist ipp.txt
client-to-client
client-connect ${SCRIPT_PATH}/client_connect.sh
client-disconnect ${SCRIPT_PATH}/client_disconnect.sh
up ${SCRIPT_PATH}/up.sh
down ${SCRIPT_PATH}/down.sh
keepalive 10 120
persist-key
persist-tun
script-security 3
status openvpn-status.log
log openvpn.log
log-append openvpn.log
verb 3
push "topology subnet"
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS ${ip_segment%.*}.1"
${extra_config}
EOF
procd_open_instance "$CONFIG"
procd_set_param command "$PROG" \
--cd "${TMP_OVPN_PATH}" \
--config "server.conf"
procd_set_param file "${TMP_OVPN_PATH}/server.conf"
procd_set_param file "${_ca}"
procd_set_param file "${_cert}"
procd_set_param file "${_key}"
procd_set_param file "${_dh}"
procd_set_param term_timeout 15
procd_set_param respawn
procd_append_param respawn 3600
procd_append_param respawn 5
procd_append_param respawn -1
procd_close_instance
ipt_rule add
gen_include
}
stop_service() {
ipt_rule del
rm -rf /var/etc/${CONFIG}.include
rm -rf ${TMP_OVPN_PATH}
}
reload_service() {
restart
}
service_triggers() {
procd_add_reload_trigger "${CONFIG}"
}