Outra solução é usar um LaunchDaemon para monitorar um diretório específico e inicie um script externo sempre que o diretório tiver modificações. A Mac Developer Library fornece uma esboço de tal script (o exemplo deles monitora /etc/hostconfig
e executa syslog -s -l notice "somebody touched /etc/hostconfig"
sempre que o horário de modificação do arquivo é alterado.)
Para o nosso propósito, notamos que toda vez que você faz login em sua VPN, o diretório /Library/Preferences/SystemConfiguration
é modificado. Então, se você salvar o seguinte arquivo plist dentro de /Library/LaunchDaemons/vpn.connectscript.plist
, ele irá ver o diretório:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>vpn.connectscript</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>/opt/local/bin/vpn_some_script.sh</string>
</array>
<key>WatchPaths</key>
<array>
<string>/Library/Preferences/SystemConfiguration</string>
</array>
</dict>
</plist>
Observe que este LaunchDaemon será chamado para mais do que apenas sua conexão VPN (por exemplo, toda vez que você se conectar a wifi). Portanto, seu script /opt/local/bin/vpn_some_script.sh
deve ter uma verificação de que o encapsulamento está realmente conectado e o script não deve criar problemas se for executado várias vezes seguidas. (Então, se você montar compartilhamentos, você pode querer verificar se eles já não estão montados).
Por exemplo, meu script /opt/local/bin/vpn_some_script.sh
é simplesmente:
#!/bin/bash
# This only changes the routes table if utun0 exists.
# -n checks that 'ifconfig utun0' returns something other than "" on STDOUT
# The 2> /dev/null redirects STDERR to null, to silence errors
if [[ -n 'ifconfig utun0 2> /dev/null' ]] ; then
route -n add -net 10.0.0.0/8 -interface utun0
# Find the old default gateway
GATEWAY='route -n get default -ifscope en0 | grep gateway | awk '{ print $2 }''
# make everything (except blocks described above) go through old default gateway rather than VPN
route -n change default $GATEWAY
fi
que só adiciona a rota a 10.0.0.0/8 através do túnel se eu estiver conectado ao túnel VPN (e mudo o padrão para ir ao roteador 192.168.1.1).
Quando você salva o arquivo plist, ele será automaticamente carregado na próxima reinicialização. No entanto, você também pode carregá-lo manualmente com:
sudo launchctl load -w /Library/LaunchDaemons/vpn.connectscript.plist
Observe que, se o seu script bash precisar de permissões de root (por exemplo, meu script que altera a tabela de roteamento), será necessário armazená-lo em /Library/LaunchDaemons/
(ou /System/Library/LaunchDaemons
). Se o seu script deve ser executado como um usuário normal, você deve armazená-lo em ~/Library/LaunchAgents/
.
Se o seu script for executado como root e não quiser sofrer ataques de escalonamento de privilégios, o script bash que está sendo chamado deve estar em um diretório como /opt/local/bin/
que só pode ser modificado pelo root. Se você armazenou em dizer ~/bin
um usuário regular poderia alterar o script (ou renomear o arquivo / diretório e substituí-lo por um arquivo que eles escreveram) e obter acesso total ao seu sistema.