LINUX.ORG.RU

VPN WireGuard Open source UI GTK

 , , ,


0

2

Искал плагин под Xfce для WireGuard, так ничего нормального и не нашел. Набросал свой на скорую руку, правда python 2, но работает стабильно. На тройку что-то никак не перепишу, да не оформлю в GitHub, может здесь кому-то пригодится пока:

#!/usr/bin/python
#coding=utf-8

# RUN: sudo ./vpnwidget.py wg0-client

import gtk, json, urllib2, socket, sys, os, subprocess
import netifaces as ni

class VPNWidget:
    def __init__(self):
        self.VPN_INTERFACE_NAME = sys.argv[1]
        self.vpn_state = "down"
        self.tray = gtk.StatusIcon()
        self.tray.connect('popup-menu', self.on_right_click)
        self.get_info()

    def get_info(self):
        ipaddr = socket.gethostbyname(socket.gethostname())
        gateway = realip = city = country = " - "
        
        vpn_state_path = '/sys/class/net/' + self.VPN_INTERFACE_NAME
        self.vpn_state = "down"

        if os.path.exists(vpn_state_path):
            self.vpn_state = "up"
            self.tray.set_from_stock(gtk.STOCK_CONNECT) 
            vpn_state_text = "Подключен"
        else:
            self.tray.set_from_stock(gtk.STOCK_DISCONNECT) 
            vpn_state_text = "Отключен"

        try:
            gw = os.popen("ip -4 route show default").read().split()
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            s.connect((gw[2], 0))
            ipaddr = s.getsockname()[0]
            gateway = gw[2]

            try:
                url = 'http://ipinfo.io/json'
                response = urllib2.urlopen(url)
                data = json.load(response)

                realip = data['ip']
                city = data['city']
                country = data['country']

            except:
                self.notify_message("ОШИБКА :: Проблемы с Интернетом")

        except:
            self.notify_message("ОШИБКА :: Проблемы с интерфейсом")

        vpn_ipaddr = ""

        if self.vpn_state == "up":
            vpn_ipaddr = ni.ifaddresses(self.VPN_INTERFACE_NAME)[ni.AF_INET][0]['addr']

        result = ("VPN: " + vpn_state_text
                + "\nЧастный IP: " + ipaddr + ((", " + vpn_ipaddr) if vpn_ipaddr else "")
                + "\nШлюз: " + gateway 
                + "\nПубличный IP: " + realip 
                + "\nГород: " + city + " (" + country + ")")

        self.tray.set_tooltip((result))
        self.notify_message(result)

        return result

    def notify_message(self, message):
        subprocess.Popen(['notify-send', message])
        return
        
    def on_right_click(self, icon, event_button, event_time):
        self.make_menu(event_button, event_time)

    def make_menu(self, event_button, event_time):
        menu = gtk.Menu()

        # Меню <Подключиться>
        item_up = gtk.ImageMenuItem(gtk.STOCK_CONNECT)
        item_up.show()
        menu.append(item_up)
        item_up.connect('activate', self.run_vpn_up)

        # Меню <Отключиться>
        item_down = gtk.ImageMenuItem(gtk.STOCK_DISCONNECT)
        item_down.show()
        menu.append(item_down)
        item_down.connect('activate', self.run_vpn_down)

        # Включаем/отключаем доступность пункта меню
        if self.vpn_state == "up":
            item_up.set_sensitive(False)
            item_down.set_sensitive(True)
        else:
            item_up.set_sensitive(True)
            item_down.set_sensitive(False)

        # Меню <Обновить>
        item_refresh = gtk.ImageMenuItem(gtk.STOCK_REFRESH)
        item_refresh.show()
        menu.append(item_refresh)
        item_refresh.connect('activate', self.refresh_info)

        # Меню <О программе>
        item_about = gtk.MenuItem("О программе")
        item_about.show()
        menu.append(item_about)
        item_about.connect('activate', self.show_about_dialog)

        # Меню <Выход>
        item_quit = gtk.ImageMenuItem(gtk.STOCK_QUIT)
        item_quit.show()
        menu.append(item_quit)
        item_quit.connect('activate', gtk.main_quit)

        menu.popup(None, None, gtk.status_icon_position_menu,
                   event_button, event_time, self.tray)
    
    def run_vpn_up(self, widget):
        # Подключение
        os.system('wg-quick up ' + self.VPN_INTERFACE_NAME)
        self.get_info()

    def run_vpn_down(self, widget):
        # Отключение
        os.system('wg-quick down ' + self.VPN_INTERFACE_NAME)
        self.get_info()

    def refresh_info(self, widget):
        self.get_info()

    def show_about_dialog(self, widget):
        about_dialog = gtk.AboutDialog()
        about_dialog.set_destroy_with_parent(True)
        about_dialog.set_icon_name("VPNWidget")
        about_dialog.set_name('VPNWidget')
        about_dialog.set_version("1.0")
        about_dialog.set_copyright("(C) 2020 Денис Ткаченко")
        about_dialog.set_comments(("Программа для управления VPN (WireGuard)"))
        about_dialog.set_authors(['Денис Ткаченко <d.tkachenko88@yandex.ru>'])
        about_dialog.run()
        about_dialog.destroy()

if __name__ == "__main__":
    VPNWidget()
    gtk.main()

Просто, не знаю когда руки дойдут, чего добру пропадать, верно? :) Кстати, на ЛОР-е не хватает руководства по настройке этой замечательной штуки (WireGuard).

P.S. Используя мой скрипт, естественно, не запускайте WireGuard на клиенте в качестве сервиса. Он работает с командами wg-quick up/down, иконка программы помещается в трей, все действия с контекстного меню. Неделю пользуюсь - полет нормальный. Всем добра!

P.P.S. [АВТОЗАПУСК] Т.к. wg-quick требует прав root, то я для себя по простому закинул скрипт в автозагрузку и дал только ему права в sudoers. Есть, конечно, и другие варианты автозапуска, озвучил самый простой.



Последнее исправление: Stack77 (всего исправлений: 3)

Ответ на: комментарий от aquadon

Мне, например, удобней в отдельной иконке в трее выбрать подключиться/отключиться и вижу статус в трее. В NetworkManager у меня WiFi, Ethernet и всегда только что-то одно и я знаю что именно в данный момент подключено на память.

Просто, я так привык. У меня там много чего в трее от claws mail, etc. А еще мне больно когда говорят, что в следуюих версиях GTK больше не будет трея… Они сошли с ума…

Stack77
() автор топика
Ответ на: комментарий от Stack77

Мне, например, удобней в отдельной иконке в трее выбрать подключиться/отключиться и вижу статус в трее.

В нормальных DE это и так отдельные иконки. Если у тебя какое-то говно вместо GUI к NetworkManager и оно умеет показывать только одну иконку на все соединения — ты знаешь что делать.

В NetworkManager у меня WiFi, Ethernet и всегда только что-то одно и я знаю что именно в данный момент подключено на память.

Не пробовал перестать делать за компьютер его работу и начать жить?

А еще мне больно когда говорят, что в следуюих версиях GTK больше не будет трея… Они сошли с ума…

Нет, ты.

intelfx ★★★★★
()
Ответ на: комментарий от intelfx

Как говориться на вкус и цвет… Есть машина вообще с голой консолью (и это не сервер), потому что так удобней и для определенного спектра задач гораздо быстрее, и Иксы там мне действительно не нужны даже в варианте startx.

Нет, ты.

Проблема в том, что вменяемой альтернативы трею никто не предложил и сомневаюсь, что в ближайшее время предложат. Так и будут эти функции висеть в состоянии deprecated еще десятилетие, а то и больше.

Stack77
() автор топика
Ответ на: комментарий от Stack77

вменяемой альтернативы трею никто не предложил и сомневаюсь, что в ближайшее время предложат.

Так и не нужно.

Так и будут эти функции висеть в состоянии deprecated еще десятилетие, а то и больше.

Свое десятилетие висения в deprecated ты уже исчерпал, выбрав Python 2.

t184256 ★★★★★
()
Ответ на: комментарий от t184256

Свое десятилетие висения в deprecated ты уже исчерпал, выбрав Python 2.

Это всего лишь инструмент. Была часть заготовки кода на v2, я её просто взял и дописал нужное. Если бы у меня была цель писать функционал для прода, а не для личных нужд, то естественно выбрал бы Python 2. А так, зачем? Чтобы лишнее время потратить?

Stack77
() автор топика
Ответ на: комментарий от Stack77

Ну, если ты сейчас портируешь на тройку за отрицательное время, тогда, конечно, да, все правильно сделал.

t184256 ★★★★★
()
Ответ на: комментарий от t184256

Может и не буду портировать (хотя это, в принципе, займет времени не больше, чем я вам здесь на сообщения отвечаю :D). Я Вам всего лишь ответил, что ЯП - это инструмент и если мне для личных нужд в тот момент было удобней и быстрее написать «микрокод» (в плане объема) на v2, то я её и выбрал. Не вижу причин поступать иначе.

Stack77
() автор топика
Ответ на: комментарий от Stack77

Проблема в том, что вменяемой альтернативы трею никто не предложил и сомневаюсь, что в ближайшее время предложат

у меня вайргард стартует systemd в отдельном сетевом неймспейсе, никакой трей не нужен.

vvviperrr ★★★★★
()
Ответ на: комментарий от vvviperrr

Покажи как делал, а то я обмазался костылями пропатчив wg-quick и у меня стойкое чувство, что это страшный костыль, хотя сам wg неймспейсы из коробки очень красиво умеет.

zink ★★
()
Ответ на: комментарий от vvviperrr

у меня вайргард стартует systemd в отдельном сетевом неймспейсе, никакой трей не нужен.

Лично я не против такого решения. Я же здесь ничего не продаю и не покупаю. Выложил скрипт - если кому-то пригодится, ок. Если нет, я не расстроюсь. Я еще раз повторюсь - решение писалось для личных нужд.

Ну, а сам трей сам по себе многом нравится и это удобно. Если кому-то он не нужен, это же не означает, что он вообще никому не нужен. Не вижу смысла здесь устраивать холивар.

Всем хорошего дня! Ушёл работать.

Stack77
() автор топика
Ответ на: комментарий от zink

я тоже обмазался костылями

netns_name=wireguard

real_ip=45.62.213.45
wg_ip=192.168.177.4

ext_iface=eno1

do_start() {
	#netns config
	/bin/ip netns add $netns_name
	/bin/ip netns exec $netns_name /bin/ip link set dev lo up
	/bin/ip link add veth0 type veth peer name veth1
	/bin/ip link set veth1 netns $netns_name
	/bin/ip netns exec $netns_name /sbin/ifconfig veth1 10.10.10.2/24 up

	/sbin/ifconfig veth0 10.10.10.1/24 up
	/sbin/iptables -t nat -I POSTROUTING -s 10.10.10.0/24 -o $ext_iface -j MASQUERADE

	#wireguard config
	/bin/ip netns exec $netns_name /bin/ip link add dev wgserver type wireguard
	/bin/ip netns exec $netns_name /bin/ip address add 192.168.177.2/24 dev wgserver
	/bin/ip netns exec $netns_name /usr/bin/wg setconf wgserver /etc/wireguard/wireguard-server.conf
	/bin/ip netns exec $netns_name /bin/ip link set up dev wgserver

	#route via wireguard
	/bin/ip netns exec $netns_name /sbin/route add $real_ip gw 10.10.10.1
	/bin/ip netns exec $netns_name /sbin/route add default gw $wg_ip

	#route to wireguard
	/sbin/route add -net 192.168.177.0/24 gw 10.10.10.2
	/bin/ip netns exec $netns_name /sbin/iptables -t nat -I POSTROUTING -s 10.10.10.0/24 -o wgserver -j MASQUERADE
}

do_stop() {
	/bin/ip netns exec $netns_name /bin/ip link del dev wgserver
	/bin/ip netns delete $netns_name
	/bin/ip link del veth0
}

cmd=$1

if [[ $cmd = "start" ]]; then
	do_start
elif [[ $cmd = "stop" ]]; then
	do_stop
else
	echo "unknown command: $1"
	exit 1
fi

exit 0
vvviperrr ★★★★★
()
Последнее исправление: vvviperrr (всего исправлений: 3)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.