OpenVPN por controle de tráfego do cliente
Para ter uma solução simples para controle de tráfego por cliente, você pode fazer algo como o seguinte. Essa solução funciona apenas para uma sub-rede /24
VPN. Testado no Ubuntu 14.04.
Configuração de exemplo do servidor OpenVPN:
port 1194
proto udp
dev tun
topology subnet
server 10.8.0.0 255.255.255.0
keepalive 10 60
comp-lzo
persist-key
persist-tun
log /var/log/openvpn.log
verb 3
#user openvpn
#group nogroup
script-security 2
down-pre
up /etc/openvpn/tc.sh
down /etc/openvpn/tc.sh
client-connect /etc/openvpn/tc.sh
client-disconnect /etc/openvpn/tc.sh
Script de controle de tráfego /etc/openvpn/tc.sh
:
#!/bin/bash
TC=$(which tc)
interface="$dev"
interface_speed="100mbit"
client_ip="$trusted_ip"
client_ip_vpn="$ifconfig_pool_remote_ip"
download_limit="512kbit"
upload_limit="10mbit"
handle='echo "$client_ip_vpn" | cut -d. -f4'
function start_tc {
tc qdisc show dev $interface | grep -q "qdisc pfifo_fast 0"
[ "$?" -gt "0" ] && tc qdisc del dev $interface root; sleep 1
$TC qdisc add dev $interface root handle 1: htb default 30
$TC class add dev $interface parent 1: classid 1:1 htb rate $interface_speed burst 15k
$TC class add dev $interface parent 1:1 classid 1:10 htb rate $download_limit burst 15k
$TC class add dev $interface parent 1:1 classid 1:20 htb rate $upload_limit burst 15k
$TC qdisc add dev $interface parent 1:10 handle 10: sfq perturb 10
$TC qdisc add dev $interface parent 1:20 handle 20: sfq perturb 10
}
function stop_tc {
tc qdisc show dev $interface | grep -q "qdisc pfifo_fast 0"
[ "$?" -gt "0" ] && tc qdisc del dev $interface root
}
function filter_add {
$TC filter add dev $interface protocol ip handle ::${handle} parent 1: prio 1 u32 match ip ${1} ${2}/32 flowid 1:${3}
}
function filter_del {
$TC filter del dev $interface protocol ip handle 800::${handle} parent 1: prio 1 u32
}
function ip_add {
filter_add "dst" $client_ip_vpn "10"
filter_add "src" $client_ip_vpn "20"
}
function ip_del {
filter_del
filter_del
}
if [ "$script_type" == "up" ]; then
start_tc
elif [ "$script_type" == "down" ]; then
stop_tc
elif [ "$script_type" == "client-connect" ]; then
ip_add
elif [ "$script_type" == "client-disconnect" ]; then
ip_del
fi
Note que, este é um script muito simples para fins de teste de tc
, uma abordagem mais sofisticada para o controle de tráfego do OpenVPN pode ser encontrada em esta resposta .
Torne o script executável:
chmod +x /etc/openvpn/tc.sh
Executando script como root no modo sem privilégios
Se você executar o OpenVPN no modo não privilegiado e o script precisar ser executado como root
, modifique as seguintes diretivas na configuração do servidor:
user openvpn
group nogroup
up "/usr/bin/sudo /etc/openvpn/tc.sh"
down "/usr/bin/sudo /etc/openvpn/tc.sh"
client-connect "/usr/bin/sudo /etc/openvpn/tc.sh"
client-disconnect "/usr/bin/sudo /etc/openvpn/tc.sh"
Adicione um usuário sem privilégios chamado openvpn
:
useradd -s /usr/sbin/nologin -r -M -d /dev/null openvpn
Edite /etc/sudoers
com o comando visudo
, adicione a seguinte linha:
# User privilege specification
openvpn ALL=NOPASSWD: /etc/openvpn/tc.sh
Salve e saia com Ctrl + x , y
Faça o script apenas gravável por root:
chown root:root /etc/openvpn/tc.sh
chmod 700 /etc/openvpn/tc.sh
Por favor, note que isso pode abrir um buraco de segurança e pode ser comparável à execução do OpenVPN como root. Embora pareça bastante seguro para mim, mas sempre há pessoas com olhos melhores:)
Resolução de problemas
O script deve ser executado como root agora. Você pode solucioná-lo adicionando as seguintes linhas ao início do script tc.sh
:
#!/bin/bash
exec >>/tmp/ov.log 2>&1
chmod 666 /tmp/ov.log 2>/dev/null
echo
date
id
echo "PATH=$PATH"
printenv
Assim que o servidor é iniciado pela primeira vez, você pode alterar os registros:
tail -f /var/log/openvpn.log /tmp/ov.log