Как программно управлять WiFi маршрутизатором TP-Link с помощью Python requests
Однажды передо мной встала задача реализации программного управления одним из распространенных домашних Wi-Fi маршрутизаторов TP-Link TL-WR841N, у которого, к сожалению, нет интерфейса управления через командную строку (telnet, SSH). Я хотел, чтобы мой Telegram бот, реализованный на Python на базе SBC в локальной домашней сети, на основе моих команд выполнял следующие функции управления маршрутизатором:
- Перезагрузка маршрутизатора
- Открытие/закрытие NAT Port Forwarding к внутренним WEB-сервисам
- Открытие/закрытие удаленного доступа к маршрутизатору из WAN (интернет)
- Определение устройств, зарегистрированных в локальной WiFi сети маршрутизатора
Для доступа к управлению маршрутизатором я использовал единственный доступный интерфейс — пользовательский WEB-интерфейс, взаимодействие с которым реализовал с помощью HTTP запросов Python requests. Для того, чтобы определить, какие HTTP GET запросы необходимо направлять на маршрутизатор, я использовал всем известный сниффер трафика Wireshark. Проще говоря, я с помощью Python requests воспроизвел те запросы, которые увидел в Wireshark, в необходимой последовательности.
Импорт, авторизация и исходные параметры
Итак, прежде всего импортируем в Python библиотеку requests, на базе которой мы будем реализовывать HTTP запросы.
В качестве исходных параметров укажем внутренний IP адрес маршрутизатора в виде строки HTTP запроса. В моем случае это 192.168.0.1.
Для авторизации нам понадобится токен, вычисление которого осуществляется на основе логина и пароля пользователя. Функция вычисления токена задана в JS скрипте на маршрутизаторе 192.168.0.1/login/encrypt.js. Выглядит он вот так.
Но, признаюсь, я не стал портировать эту функцию из JS в Python. Я упростил подход и посмотрел значение параметра, которое отправляет мой браузер в Wireshark.
Выделенный запрос — это запрос авторизации, который мы воспроизведем чуть позже. Таким образом, я скопировал параметр Cookie pair в запросе авторизации
Пожалуй, это не самый изящный, но простой подход. Кроме того, мы не будем хранить логин и пароль от маршрутизатора в текстовом открытом виде, что, на мой взгляд, не так плохо.
Перейдем к функции авторизации.
Цикл while я использовал, так как маршрутизатор не всегда авторизовывал моего бота с первого раза. Возможно, у вас получится обойтись без него.
В случае успешной авторизации функция возвращает значение session_id. Это идентификатор сессии, который генерирует маршрутизатор при авторизации. После прохождения авторизации session_id должен присутствовать во всех последующих HTTP запросах к маршрутизатору.
Далее реализуем функцию выхода logout.
Я делаю logout после каждой операции, так как маршрутизатор позволяет одновременно подключаться только одному пользователю. Поэтому, если ваш бот авторизуется и не выйдет из маршрутизатора, то вы не сможете на него зайти до тех пор, пока маршрутизатор не закроет открытую сессию по таймауту через несколько минут. Таким образом, я решил строго придерживаться последовательности «login -> операция -> logout».
Кстати, стоит учесть, что, если кто-то уже авторизован на маршрутизаторе, то бот, очевидно, не сможет авторизоваться до тех пор, пока пользователь не сделает logout, или активная сессия не закроется по таймауту. Одним словом, «кто первый встал, того и тапки.» Стоит отметить, что Python бот выполняет операции управления маршрутизатором за доли секунд. Таким образом, ваш маршрутизатор не будет занят ботом в течении продолжительного времени.
Перезагрузка, NAP Port Forwarding
Перейдем к операциям, которые мы можем выполнять после успешной авторизации.
Здесь я бы хотел подчеркнуть, что указанные запросы активируют/деактивируют все правила Port Forwarding, созданные ранее в соответствующем разделе управления маршрутизатором.
Проще говоря, запросы аналогичны нажатию кнопок «Включить все» и «Отключить все». По аналогии можно реализовать и создание/активацию отдельных правил.
Удаленный доступ к маршрутизатору из WAN (интернет)
Здесь параметр remote_ip задает IP-адрес удаленного управления, т.е. тот IP адрес, с которого разрешено удаленно заходить на маршрутизатор через интернет.
При желании можно указывать конкретный IP адрес, с которого вы хотите удаленно подключиться к маршрутизатору.
Определение списка подключенных устройств
Для чего нужен функционал определения устройств, зарегистрированных в домашней сети WiFi. Допустим, у меня есть смартфон с WiFi и MAC адресом DC-31-54-97-51-06. Когда я прихожу домой, мой смартфон регистрируется в домашней сети WiFi. Таким нехитрым способом я могу отслеживать свое присутствие (а точнее, присутствие своего смартфона) в домашней сети (т.е. дома). Этот функционал позволяет автоматизировать ряд функций, связанных с определением моего присутствия. Например, когда я прихожу домой, отключается детектор движения камеры наблюдения и т.д. Ранее я использовал определение присутствия устройств в сети с помощью Ping’а их IP адресов, но в итоге разочаровался в данном методе, так как смартфоны, как оказалось, неохотно и не всегда отвечают на Ping. Дополнительно я использую сниффер ARP пакетов, реализованный на Python, который позволяет отследить момент регистрации устройства с определенным MAC адресом в сети WiFi.
Итак, r.text в коде выше возвращает среди прочего список MAC адресов устройств, зарегистрированных в WiFi сети маршрутизатора. Что вы будете делать с этим списком, зависит только от вашей фантазии.
Итак, мне остается только подытожить. Весь код выглядит следующим образом.
How to connect to WiFi network on Windows?
I am trying to write a script in Python 3 but all modules available today work on python 2 which will enable me to search for wireless networks and to connect to them. Is there any Python 3 library for this?
The code I tried for python 2
which is giving me an error
But this is not working since it is based on python 2. Is there any way to connect to a wifi using Python 3
3 Answers 3
To connect wifi using python in windows, the better option is to use the winwifi module:
I recommend you to install plumbum before installing winwifi. This is the link to download plumbum: https://pypi.org/project/plumbum/
After this install winwifi from here:https://pypi.org/project/winwifi/ It’s better to install it in 32-bit python folder.
After installing you could check the module by the following code (This is to connect router which was connected to the device before) :
On running this code on your IDLE, you could see that the wifi is connected to your device. If you want to connect a new device you could use the code after adding profile:
You can disconnect the current Wifi using the command:
There are many more commands on this module, try to explore them. Just refer to the main.py file in winwifi folder for many more.
Is there a pressing need for this to be a library? It can be achieved easily without one (or if you prefer, save it as a module and import it).
If the wireless interface is wlan and the SSID and Profile name are the same (usually true) then just use
In the snippet above, tt is the name of the SSID you wish to connect to — it’s a variable in my code because it connects to different SSIDs in turn.
I know that using subprocess is something of a kludge, but the snippet above doesn’t add any significant overhead.
This is part of a script I wrote to ‘harvest’ data from my parents’ solar inverters: the inverters have their own SSID, so the script has to connect to each in turn; fetch real-time data using requests ; store the data in a PostgreSQL db; and then reconnect to household wifi.
I know the devices also store historical data, however the data API was disabled by the manufacturer in
2018 to drive owners towards their app (hence giving them user data to package and sell).
Does not (yet) support Python 3: as somewhere in the code it uses the cmp function (which is only available in Python 2)
- I wanted to submit a pull request (as the fix is trivial), but apparently on GitHub it was already fixed, yet the PyPI repository was not updated (since 2016)
Does not work on Win (only Nix drivers are listed on the homepage — basically it only launches shell commands)
As a consequence, I’d suggest looking for alternatives:
- One that I’ve encountered a couple of days ago is Win32Wifi: ([PyPI]: win32wifi, although this wasn’t updated since 2017 either). Check [SO]: Unable to get all available networks using WlanGetAvailableNetworkList in Python (@CristiFati’s answer) for more details (might also check [SO]: Force wifi scan using WlanScan in Python (@CristiFati’s answer))
Alright, after a lot of browsing of:
Win32Wifi source code
, I was able to come up with something.
Output:
Notes:
In order to create a POC I had to add some code (e.g. wireless_disconnect) not necessarily related to the question, which adds complexity.
BTW, the code is waaay more complex than I initially anticipated (that’s why I didn’t bother to explain it — as it would be an overkill), but I don’t see any way of trimming it down
script00.bat (and time <nul ) are just to prove in console that the code is connecting / disconnecting from the wireless network (and that I’m not connecting from Win in parallel)
- I don’t know where the "*** 0***" part from time 0<nul (in the output) comes from
As I specified, this is more like a POC, there are some limitations in (my and Win32Wifi) code. Some scenarios (networks) might not work without (small) code changes
Although connection to the network succeeds (and works), in the System Tray, the network status still appears as disconnected (actually for a fraction of a second it appears connected, but then it automatically changes). Also, the System Tray network icon shows as Connected. I’m not sure whether this is on my side (I forgot to somehow notify Win — although this doesn’t make much sense), or Win doesn’t like "someone else" to connect to wireless networks
THE MOST IMPORTANT ONE: The above code will not work OOTB, because Win32Wifi is buggy. I found 2 bugs that are fatal (critical) for this scenario, and a bunch of other smaller ones.
I’ve just submitted [GitHub]: kedos/win32wifi — Fixes (some critical) and improvements (merged on 200906, but no update on PyPI)
Wifi -Hacking using PyWifi
Hello Medium,
Hope You all doing good.
Lets try something dangerous.
Again this blog is for education purpose only.
Tighten Your seatbelt
Lets start with a bit of theory and module →
You must have python3.6 or python3.7 installed in your computers.
Pywifi → This module provides a cross-platform Python module for manipulating wireless interfaces.
You can install by → pip install pywifi
and read about it here → https://github.com/awkman/pywifi/blob/master/DOC.md
Wifi profiles are saved in xml format in our computers and also their is a procedure which we need to follow in order to add new profiles and connect to any profile.
Here Profile means your wifi profile i.e → ssid and other information needed by your computer to connect to wifi.
This is a brute force method so it takes large amount of time depending upon how much information you have about key and length of password wordlist.
Lets start the Coding part→
Lets Begin the explanation→
client_ssid → name of your wifi network that you want to hack
path_to_file → path to python wordlist containing password
You can use your own python wordlist depending upon information you have about password.
If you don’t know how to create follow → https://rsajal.medium.com/python-wordlist-for-brute-force-password-cracking-9a8c62170bd2
These are color variables you don’t need to change them they are initialized to make command prompt look fancy and interactive we will see how later.
In this part we are initializing the piwifi module so that we can interact with the wifi interface from computer
argparse → This module is used for making command line interactive.
You can read about it from official tutorial here →
https://docs.python.org/3/howto/argparse.html
So basically we are trying to pass two important variables client_ssid and path_to_file by hard-coding or by command line depending upon the use.
If you want to pass by Command Line Your syntax will go somewhat like →
if you want to hardcode it → go by changing client_ssid and wordlist path variable.
In this part we taking arguments from command line in args and checking if user has given them from command line . If not take the one from hard code
Then we are trying to find file and cracking the wifi password
This part opens the file and fetches each word written in it and send it to main function.
THE MAIN FUNCTION →
As the name suggests this function is main culprit of the process. Main function requires three things → password, number , ssid which are send from pwd function .Then we are creating the profile that would be compatible with our operating system which looks like →
This is what module creates as profile. You don’t have to worry about it.
keymaterial will change as password changes and it will try to connect you to wifi.
Connect to a WiFi network in Python
Connecting a computer to the internet has become inevitable now. The connection can be made either with Ethernet technology or Wi-Fi technology. Though every Operating System offers way with its simple easy GUI, using the Python script has a nice ring to it. This article explains how a computer can be connected to the internet with Wi-Fi technology using a Python script in Windows and Linux operating systems.
The netsh and nmcli
netsh is a command-line tool in Windows that offers various facilities for networking. To add a new Wi-Fi connection, Windows requires the credentials to be stored in an XML file. nmcli is a command-line tool in the Linux distributions that offers facilities for networking. Unlike Windows netsh , nmlci is quite simple to use. These commands are used in the Python script to connect to a network.
A Python script to connect with Wi-Fi network
Typing a series of commands every time for connecting to a network can be annoying. With the knowledge of the commands, a Python script can be used to do it. The script works by executing the commands in a subshell. Here is a Python script that connects to a Wi-Fi network, given its name and password (for new networks).
The script uses platform.system() to identify commands for the appropriate platform. Here the commands are executed in a subshell with os.system() method with a command as its argument. getpass() is a method that can make password invisible when typed. The try-except is used to prevent any runtime exceptions.
Running the script in Windows produces the following output.
Output when connecting to a known network
Output when connecting to a new network
Running the script in Linux produces some pretty output.
Output when connecting to a known network
Output when connecting to a new network
I hope you have understood and able to connect with the WiFi network by yourself by writing code in Python.