Ten przewodnik przeprowadza Państwa od zwykłego VPN na MikroTiku do takiego, w którym każde logowanie trzeba zatwierdzić dotknięciem w aplikacji Notakey Authenticator, przy użyciu wyłącznie skryptów RouterOS. W tej konfiguracji nie ma serwera RADIUS ani auth-proxy, nie trzeba też wdrażać w sieci niczego poza routerem, który Państwo już mają.
Wszystkie skrypty pochodzą z oficjalnego repozytorium
notakey/mikrotik-2fa-vpn.
Jak to działa
Zrozumienie przebiegu sprawia, że każdy z poniższych kroków staje się oczywisty:
- Użytkownik nawiązuje połączenie VPN i uwierzytelnia się jak zwykle nazwą
użytkownika oraz hasłem. Sesja PPP zostaje zestawiona, ale zapora sieciowa
natychmiast blokuje cały jego ruch, ponieważ jego adres trafia na listę
adresów
vpn_pending. - Uruchamia się skrypt up profilu PPP. Wywołuje on Państwa Notakey Authentication Server, który wysyła żądanie zatwierdzenia na telefon użytkownika: „Log in as <user> from <caller IP>?”
- Jeśli użytkownik zatwierdzi w wyznaczonym czasie (60 sekund), skrypt
usuwa jego adres z
vpn_pending: blokada zapory znika, a ruch zaczyna płynąć. - Jeśli użytkownik odrzuci żądanie lub upłynie limit czasu, skrypt kończy sesję PPP. Samo hasło nigdy nie wystarczało.
Wymagania
- RouterOS 6.46.4 lub nowszy (skrypty działają również na RouterOS 7.x).
- Działający VPN oparty na PPP na routerze (L2TP/IPsec, PPTP lub SSTP), z którym użytkownicy potrafią już łączyć się za pomocą nazwy użytkownika i hasła.
- Notakey Authentication Server osiągalny z routera. Wystarczy darmowy plan w chmurze pod adresem signup.notakey.com (pierwszych 6 użytkowników za darmo) lub uruchomienie lokalnego appliance (pierwszych 10 użytkowników za darmo).
- Telefon z systemem iOS lub Android z zainstalowaną aplikacją Notakey Authenticator.
Krok 1: Przygotowanie strony Notakey
- W panelu Notakey należy utworzyć nową aplikację (usługę) dla VPN i nadać jej rozpoznawalną nazwę, np. „Office VPN”; to właśnie tę nazwę użytkownicy zobaczą na telefonie.
- Skopiować Access ID aplikacji (identyfikator UUID). Zostanie on wklejony do skryptu routera w kroku 4.
- Utworzyć użytkownika (lub podłączyć własne źródło użytkowników) i skonfigurować wymaganie rejestracji, a następnie zarejestrować telefon: zainstalować Notakey Authenticator, dodać usługę i ukończyć rejestrację.
Nazwa użytkownika w Notakey musi dokładnie odpowiadać nazwie użytkownika
VPN: skrypt routera używa nazwy użytkownika PPP do zaadresowania
powiadomienia push. john na routerze i john.doe w Notakey zawiodą bez
żadnego komunikatu.
Krok 2: Instalacja biblioteki JParseFunctions
Skrypty RouterOS nie potrafią natywnie parsować formatu JSON; tę lukę wypełnia właśnie ta biblioteka (z projektu mikrotik-json-parser).
W WinBox lub WebFig należy przejść do System → Scripts, utworzyć nowy
skrypt o nazwie dokładnie JParseFunctions, pozostawić pola wyboru zasad w
wartościach domyślnych (nie są wymagane żadne specjalne uprawnienia) i wkleić
całą zawartość
pliku JParseFunctions
z tego projektu.
Krok 3: Instalacja biblioteki NotakeyFunctions
Ta sama procedura: należy utworzyć drugi skrypt o nazwie dokładnie
NotakeyFunctions i wkleić zawartość
NotakeyFunctions.lua
z repozytorium Notakey. To klient komunikujący się z API Notakey: tworzy
żądanie uwierzytelnienia i odpytuje o odpowiedź użytkownika.
Nazwy skryptów mają znaczenie: skrypt profilu w następnym kroku ładuje obie biblioteki po nazwie.
Krok 4: Podłączenie skryptów up/down do profilu PPP
Należy otworzyć profil PPP Państwa VPN (PPP → Profiles) albo utworzyć osobny, aby na czas testów 2FA objąć nim tylko wybranych użytkowników.
- Na karcie General należy ustawić Address List na
vpn_pending. Każde nowe połączenie korzystające z tego profilu będzie teraz dodawać swój adres do tej listy w chwili zestawienia sesji. - Na karcie Scripts należy wkleić poniższy skrypt On Up (z
PppProfileScript.lua) do pola On Up, zmieniając dwie wartości pod własne środowisko:ntkHost, czyli nazwę hosta Państwa serwera Notakey (bezhttps://), orazntkAccessId, czyli Access ID aplikacji skopiowany w kroku 1.
{
:local localAddr $"local-address";
:local remoteAddr $"remote-address";
:local callerId $"caller-id";
:local calledId $"called-id";
:log info "$user (srcIp=$callerId, dstIp=$calledId) connected: was given $remoteAddr IP (GW $localAddr)";
/system script run "JParseFunctions";
:global JSONUnload;
/system script run "NotakeyFunctions";
:global NtkAuthRequest;
:global NtkWaitFor;
:global NtkUnload;
# Change values below to match your Notakey installation
:local ntkHost "demo.notakey.com";
:local ntkAccessId "12345645-b32b-4788-a00d-251cd7dc9a03";
# Custom message in authentication request
:local authDescMsg "Log in as $user from $callerId\?";
:local ntkAuthUuid ([$NtkAuthRequest host=$ntkHost accessId=$ntkAccessId authUser=$user authTitle="VPN connection" authDesc=$authDescMsg authTtl=60]);
:if ([$NtkWaitFor uuid=$ntkAuthUuid host=$ntkHost accessId=$ntkAccessId]) do={
# Remove blocking rule after successful 2FA authentication
/ip firewall address-list remove [/ip firewall address-list find where list=vpn_pending address=$remoteAddr]
} else={
:log info "VPN 2FA authentication failure for user $user from IP $callerId";
# Disconnect active session with this IP and user
/ppp active remove [/ppp active find name="$user" address="$remoteAddr"]
}
$NtkUnload
$JSONUnload
}
Skrypt On Down z tego samego pliku jedynie zapisuje w logu rozłączenie. Można go wkleić do pola On Down, aby mieć uporządkowane logi, lub pominąć.
Limit czasu na zatwierdzenie (authTtl) wynosi 60 sekund: wystarczająco
długo, by wyjąć telefon z kieszeni, i wystarczająco krótko, by zawieszone
logowanie nie utrzymywało w nieskończoność wpół otwartej sesji.
Krok 5: Dodanie reguł zapory sieciowej
To reguła drop sprawia, że lista oczekujących naprawdę coś znaczy:
/ip firewall filter
add chain=forward src-address-list=vpn_pending action=drop \
comment="Block VPN clients pending 2FA approval"
Należy umieścić ją nad ogólnymi regułami zezwalającymi na ruch VPN, aby miała
pierwszeństwo, dopóki zatwierdzenie jest w toku. Jeśli klienci VPN mają być
również blokowani przed dostępem do samego routera, powiel tę regułę w
łańcuchu input.
Jeden szczególny przypadek: jeśli zatwierdzenie ma nastąpić na tym samym urządzeniu, które nawiązuje połączenie VPN (gdy klientem VPN jest sam telefon), ruch zatwierdzający musi mieć możliwość dotarcia do serwera Notakey, podczas gdy cała reszta jest wciąż zablokowana. Należy dodać regułę accept nad regułą drop:
/ip firewall filter
add chain=forward src-address-list=vpn_pending dst-address=<notakey-server-ip> \
action=accept comment="Let pending clients reach Notakey for approval"
(Zatwierdzanie z drugiego urządzenia, gdy telefon zatwierdza, a połączenie
nawiązuje laptop, nie wymaga dodatkowej reguły: router sam odpytuje API
Notakey, a jego własny ruch nie podlega łańcuchowi forward.)
Krok 6: Przypisanie profilu i test
Należy skierować użytkownika VPN (PPP → Secrets) na profil z kroku 4, a następnie nawiązać połączenie VPN z klienta:
- Tunel się łączy, ale nic nie jest routowane: klient jest na liście
vpn_pending. - W ciągu sekundy lub dwóch powiadomienie push pojawia się na telefonie.
- Zatwierdzenie → ruch zaczyna płynąć. Odrzucenie lub brak reakcji → po upływie limitu czasu sesja zostaje zerwana.
Można to śledzić w Log (skrypty zapisują każde żądanie i jego wynik) oraz
w IP → Firewall → Address Lists, gdzie adres klienta pojawia się na liście
vpn_pending i znika po zatwierdzeniu.
Wdrożenie u wszystkich użytkowników
Ustawienie profilu na pojedynczym wpisie secret to bezpieczny sposób na testy,
bo 2FA obejmuje wtedy tylko tego jednego użytkownika. Gdy już wszystko działa,
nie trzeba edytować każdego wpisu z osobna. Każdy serwer PPP ma ustawienie
Default Profile, które dotyczy wszystkich użytkowników, których
wpis secret pozostaje na profilu default. W przypadku L2TP znajduje się ono w
PPP → Interface → L2TP Server. Ta sama zmiana z poziomu terminala (w
WinBox: New Terminal):
/interface l2tp-server server set default-profile=<your-2fa-profile>
SSTP i PPTP mają to samo ustawienie pod własnymi przyciskami serwera. Profil ustawiony bezpośrednio na wpisie secret nadal ma pierwszeństwo przed profilem domyślnym serwera, więc użytkownik świadomie skierowany na inny profil przy nim pozostanie.
Rozwiązywanie problemów
- Nic się nie dzieje, a w logu nie ma żadnego żądania. Skrypt w ogóle się nie uruchomił, co oznacza, że żadne połączenie nie skorzystało z profilu 2FA. Samo utworzenie profilu nie wystarczy: musi na niego wskazywać albo wpis secret użytkownika, albo ustawienie Default Profile serwera.
- Push nie dociera. Niemal zawsze jest to niezgodność nazwy użytkownika między PPP Secrets a usługą Notakey albo telefon nigdy nie został zarejestrowany w tej konkretnej aplikacji.
- Push dociera, ale nie da się go zatwierdzić. Prawdopodobnie zatwierdzenie następuje z tego samego urządzenia, które nawiązuje połączenie VPN, a reguła drop dla listy oczekujących blokuje ruch zatwierdzający. Należy dodać regułę accept z kroku 5 lub zatwierdzać z urządzenia, które nie znajduje się w tunelu.
- Tekst żądania jest zniekształcony lub żądanie kończy się niepowodzeniem. Biblioteka parsera JSON nie radzi sobie z nawiasami (i prawdopodobnie innymi znakami specjalnymi) w wiadomości uwierzytelniającej. Treść wiadomości należy zachować prostą.
- Działa dla jednego użytkownika, dla innego nie. Należy sprawdzić, jaki profil
ostatecznie otrzymuje drugi użytkownik. Albo jego wpis secret wskazuje na
profil 2FA, albo wpis pozostaje na profilu
default, a serwer ma profil 2FA ustawiony jako Default Profile.
Gdzie to znajduje zastosowanie
To podejście oparte na skryptach jest najszybszą drogą do 2FA dla VPN MikroTik i nie wymaga dodatkowej infrastruktury. Jeśli z czasem Państwo z niego wyrosną (wiele routerów, inni dostawcy VPN lub centralna polityka), ten sam serwer Notakey obsługuje konfigurację opartą na RADIUS, w której zamiast skryptów routera przepływem zatwierdzeń zarządza auth-proxy.