Jak utworzyć połączenie VPN przez terminal?

9

Mam MacBooka Pro z uruchomionymi maverickami. Szukam sposobu połączenia z siecią VPN w terminalu.

Powodem, dla którego chcę to zrobić, jest to, że chcę napisać mały program w języku Python, który automatycznie wykrywa najszybszy serwer VPN spośród 30 serwerów. Jest to sam motywujący projekt ćwiczeniowy, więc myślę, że będę trzymać się języka Python. Rozbijam więc zadanie i myślę, że program może najpierw połączyć się z jednym z serwerów, a następnie uruchomić test prędkości.

Więc utknąłem w tym pierwszym kroku, ponieważ zdałem sobie sprawę, że ustanowienie połączenia VPN wydaje się być na poziomie systemu, ponieważ nie mogę znaleźć wstępnie napisanego modułu VPN w pythonie. Sądzę więc, że będzie to tak, jak mówię Pythonowi, aby powiedział powłoce systemowej, aby łączyła się z serwerem VPN.

Kiedy grzebałem i znalazłem polecenie, pisząc apropos vpn. To się nazywa vpnagent. Ale man vpnagentnie dostarcza użytecznych informacji ani nie which vpnagentmówi mi, że narzędzie nie jest zainstalowane na moim komputerze Mac. Inną ciekawą rzeczą, którą znalazłem, było pppdjednak skonfigurowanie pliku konfiguracyjnego było bardzo frustrujące. Nie udało mi się tego zrobić.

Czy jest więc sposób na połączenie się z VPN przy użyciu terminala? Ponadto, ponieważ jestem nowy w programowaniu, mile widziane są również wszelkie komentarze dotyczące mojego projektu. Z góry dziękuję.

Choushishi
źródło

Odpowiedzi:

6

Możesz użyć tych wspaniałych funkcji bash z @slhck w Super User :

Aby połączyć się z różnymi VPN, miej wiele VPN w Network.prefpane.

function vpn-connect {
/usr/bin/env osascript <<-EOF
tell application "System Events"
        tell current location of network preferences
                set VPN to service "UniVPN" -- your VPN name here
                if exists VPN then connect VPN
                repeat while (current configuration of VPN is not connected)
                    delay 1
                end repeat
        end tell
end tell
EOF
}
function vpn-disconnect {
/usr/bin/env osascript <<-EOF
tell application "System Events"
        tell current location of network preferences
                set VPN to service "UniVPN" -- your VPN name here
                if exists VPN then disconnect VPN
        end tell
end tell
return
EOF
}

Nie zapomnij zmienić nazwy VPN.

grg
źródło
Dziękuję, że działa. Ale staje się nieprzydatne, że muszę zmieniać nazwę VPN za ~/.bash-profilekażdym razem, gdy muszę połączyć się z innym VPN. Czy istnieje sposób dodania argumentu do funkcji, więc mogę wywołać jak vpn-connect UniVPN?
Choushishi
@Choushishi Możesz po prostu utworzyć wiele funkcji o różnych nazwach i różnych sieciach VPN. Zduplikuj funkcję i zmień nazwę funkcji w pierwszym wierszu i nazwę VPN.
grg
Dzięki, to dobre rozwiązanie. Myślę, że nadal będę próbował znaleźć sposób na dodanie argumentów, aby uczynić go bardziej eleganckim
Choushishi
1
@Choushishi możesz sprawić, że będzie to kłótnia, zastępując UniVPN$1. (zachowując podwójne cudzysłowy)
Timothée Boucher
6

Scutil powinien być wszystkim, czego potrzebujesz.

scutil --nc start <service name>

Tak więc twój skrypt Pythona do łączenia się z każdym z nich może zawierać coś takiego:

import re
from subprocess import call, check_output

vpns_string = check_output(["scutil", "--nc", "list"]) # lists all VPN services

vpns = re.findall('"(.+)"', vpns_string) # service names are double-quoted

for vpn in vpns:
  call(["scutil", "--nc", "start", vpn])
  #...do stuff with your connection, test speed etc.
  call(["scutil", "--nc", "stop", vpn])

Możesz opcjonalnie podać nazwę użytkownika, hasło i klucz tajny, z którymi chcesz się połączyć - sprawdź scutil --nc helpużycie.

MatzFan
źródło
2
#!/bin/sh
# Random UUID for this config
vpnUuid=``
# Address of VPN server
serverName=""
# The group of usernames that is allowed in
groupName=""
# The name of connection type displayed in GUI
labelName=""
# The Shared Secret
sharedSecret=""
# The user this VPN config is for
userName=""

# CHECK TO SEE IF A VALUE WAS PASSED IN PARAMETER 4 AND, IF SO, ASSIGN TO "serverName"
if [ "$4" != "" ] && [ "$ranAtImaging" == "" ]; then
    ranAtImaging=$4
fi

# CHECK TO SEE IF A VALUE WAS PASSED IN PARAMETER 5 AND, IF SO, ASSIGN TO "serverName"
if [ "$5" != "" ] && [ "$serverName" == "" ]; then
    serverName=$5
fi

# CHECK TO SEE IF A VALUE WAS PASSED IN PARAMETER 6 AND, IF SO, ASSIGN TO "groupName"
if [ "$6" != "" ] && [ "$groupName" == "" ]; then
    groupName=$6
fi

# CHECK TO SEE IF A VALUE WAS PASSED IN PARAMETER 7 AND, IF SO, ASSIGN TO "labelName"
if [ "$7" != "" ] && [ "$labelName" == "" ]; then
    labelName=$7
fi

# CHECK TO SEE IF A VALUE WAS PASSED IN PARAMETER 8 AND, IF SO, ASSIGN TO "sharedSecret"
if [ "$8" != "" ] && [ "$sharedSecret" == "" ]; then
    sharedSecret=$8
fi

# CHECK TO SEE IF A VALUE WAS PASSED IN PARAMETER 9 AND, IF SO, ASSIGN TO "userName"
if [ "$9" != "" ] && [ "$userName" == "" ]; then
    userName=$9
fi

loggedInUser=`/bin/ls -l /dev/console | /usr/bin/awk '{ print $3 }'`
macModel=`system_profiler SPHardwareDataType | grep "Model Name:" | awk '{ print $3 }'`

# Check that we are running this on a MacBook
if [ "$macModel" == "MacBook" ]; then

    # Setup Keychain shared secret granting appropriate access for the OS apps
    /usr/bin/security add-generic-password -a "$groupName" -l "$labelName" -D "IPSec Shared Secret" -w "$sharedSecret" -s "$vpnUuid".SS -T /System/Library/Frameworks/SystemConfiguration.framework/Resources/SCHelper -T /Applications/System\ Preferences.app -T /System/Library/CoreServices/SystemUIServer.app -T /usr/sbin/pppd -T /usr/sbin/racoon /Library/Keychains/System.keychain

    # Write a Network Config containing this keychain item directly to System Config
    /usr/libexec/PlistBuddy -c "Add :NetworkServices:$vpnUuid:DNS dict" /Library/Preferences/SystemConfiguration/preferences.plist
    /usr/libexec/PlistBuddy -c "Add :NetworkServices:$vpnUuid:IPv4 dict" /Library/Preferences/SystemConfiguration/preferences.plist
    /usr/libexec/PlistBuddy -c "Add :NetworkServices:$vpnUuid:IPv4:ConfigMethod string Automatic" /Library/Preferences/SystemConfiguration/preferences.plist
    /usr/libexec/PlistBuddy -c "Add :NetworkServices:$vpnUuid:IPv6 dict" /Library/Preferences/SystemConfiguration/preferences.plist
    /usr/libexec/PlistBuddy -c "Add :NetworkServices:$vpnUuid:Proxies dict" /Library/Preferences/SystemConfiguration/preferences.plist
    /usr/libexec/PlistBuddy -c "Add :NetworkServices:$vpnUuid:Proxies:ExceptionList array" /Library/Preferences/SystemConfiguration/preferences.plist
    /usr/libexec/PlistBuddy -c "Add :NetworkServices:$vpnUuid:Proxies:ExceptionList:0 string \*\.local" /Library/Preferences/SystemConfiguration/preferences.plist
    /usr/libexec/PlistBuddy -c "Add :NetworkServices:$vpnUuid:Proxies:ExceptionList:1 string 169\.254\/16" /Library/Preferences/SystemConfiguration/preferences.plist
    /usr/libexec/PlistBuddy -c "Add :NetworkServices:$vpnUuid:Proxies:FTPPassive integer 1" /Library/Preferences/SystemConfiguration/preferences.plist
    /usr/libexec/PlistBuddy -c "Add :NetworkServices:$vpnUuid:SMB dict" /Library/Preferences/SystemConfiguration/preferences.plist
    /usr/libexec/PlistBuddy -c "Add :NetworkServices:$vpnUuid:UserDefinedName string $labelName" /Library/Preferences/SystemConfiguration/preferences.plist
    /usr/libexec/PlistBuddy -c "Add :NetworkServices:$vpnUuid:Interface dict" /Library/Preferences/SystemConfiguration/preferences.plist
    /usr/libexec/PlistBuddy -c "Add :NetworkServices:$vpnUuid:Interface:Type string IPSec" /Library/Preferences/SystemConfiguration/preferences.plist
    /usr/libexec/PlistBuddy -c "Add :NetworkServices:$vpnUuid:IPSec dict" /Library/Preferences/SystemConfiguration/preferences.plist
    /usr/libexec/PlistBuddy -c "Add :NetworkServices:$vpnUuid:IPSec:AuthenticationMethod string SharedSecret" /Library/Preferences/SystemConfiguration/preferences.plist
    /usr/libexec/PlistBuddy -c "Add :NetworkServices:$vpnUuid:IPSec:LocalIdentifier string $groupName" /Library/Preferences/SystemConfiguration/preferences.plist
    /usr/libexec/PlistBuddy -c "Add :NetworkServices:$vpnUuid:IPSec:LocalIdentifierType string KeyID" /Library/Preferences/SystemConfiguration/preferences.plist
    /usr/libexec/PlistBuddy -c "Add :NetworkServices:$vpnUuid:IPSec:RemoteAddress string $serverName" /Library/Preferences/SystemConfiguration/preferences.plist
    /usr/libexec/PlistBuddy -c "Add :NetworkServices:$vpnUuid:IPSec:SharedSecret string $vpnUuid\.SS" /Library/Preferences/SystemConfiguration/preferences.plist
    /usr/libexec/PlistBuddy -c "Add :NetworkServices:$vpnUuid:IPSec:SharedSecretEncryption string Keychain" /Library/Preferences/SystemConfiguration/preferences.plist
    /usr/libexec/PlistBuddy -c "Add :NetworkServices:$vpnUuid:IPSec:XAuthName string $userName" /Library/Preferences/SystemConfiguration/preferences.plist
    /usr/libexec/PlistBuddy -c "Add :NetworkServices:$vpnUuid:IPSec:XAuthPasswordEncryption string Prompt" /Library/Preferences/SystemConfiguration/preferences.plist

    # At this point, we should have only one Network Set (Automatic) so we find out its UUID — errr, messy
    autoUuid=`/usr/libexec/Plistbuddy -c "Print :Sets" /Library/Preferences/SystemConfiguration/preferences.plist | grep -B1 -m1 Automatic | grep Dict | awk '{ print $1 }'`

    # and we add our newly created config to the default set
    /usr/libexec/PlistBuddy -c "Add :Sets:$autoUuid:Network:Service:$vpnUuid dict" /Library/Preferences/SystemConfiguration/preferences.plist
    /usr/libexec/PlistBuddy -c "Add :Sets:$autoUuid:Network:Service:$vpnUuid:__LINK__ string \/NetworkServices\/$vpnUuid" /Library/Preferences/SystemConfiguration/preferences.plist
    /usr/libexec/PlistBuddy -c "Add :Sets:$autoUuid:Network:Global:IPv4:ServiceOrder: string $vpnUuid" /Library/Preferences/SystemConfiguration/preferences.plist

else
    echo "This mac is not a MacBook… so skipping…"
fi
Davidcondrey
źródło