summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Poessinger <christian@poessinger.com>2021-04-24 16:52:18 +0200
committerChristian Poessinger <christian@poessinger.com>2021-04-25 09:32:05 +0200
commit92d0262d8d204189ba4ad4cfb93747fdc1b445e0 (patch)
tree16ab1f72ed1df849043e60299b328149316635ea
parent78f647485d337e63a4664c89481e03c2a15b35e9 (diff)
downloadvyos-1x-92d0262d8d204189ba4ad4cfb93747fdc1b445e0.tar.gz
vyos-1x-92d0262d8d204189ba4ad4cfb93747fdc1b445e0.zip
wireguard: T1802: generate QR code for clients on CLI
generate wireguard mobile-config wg0 server wg.vyos.net address 1.2.2.2/24 WireGuard client configuration for interface: wg0 [Interface] PrivateKey = AEXrZ4b3xFVLg1lql3hy/93+d43q3+3vPdSMUGI6/Fo= Address = 1.2.2.2/24 [Peer] PublicKey = h1HkYlSuHdJN6Qv4Hz4bBzjGg5WUty+U1L7DJsZy1iE= Endpoint = wg.vyos.net:41751 AllowedIPs = 0.0.0.0/0, ::/0 The servers public key and port are automatically extracter from the running config. (cherry picked from commit 92d62740a1dd84d27ed3006cdc8d2560673f6bca)
-rw-r--r--debian/control1
-rw-r--r--op-mode-definitions/wireguard.xml.in34
-rwxr-xr-xsrc/op_mode/wireguard_client.py92
3 files changed, 126 insertions, 1 deletions
diff --git a/debian/control b/debian/control
index fe34e4cdf..5d58f1a96 100644
--- a/debian/control
+++ b/debian/control
@@ -110,6 +110,7 @@ Depends:
python3-waitress,
python3-xmltodict,
python3-zmq,
+ qrencode,
radvd,
salt-minion,
snmp,
diff --git a/op-mode-definitions/wireguard.xml.in b/op-mode-definitions/wireguard.xml.in
index 69ba8043d..9cc979b7b 100644
--- a/op-mode-definitions/wireguard.xml.in
+++ b/op-mode-definitions/wireguard.xml.in
@@ -26,6 +26,38 @@
</properties>
<command>sudo ${vyos_op_scripts_dir}/wireguard.py --genkey --location "$4"</command>
</tagNode>
+ <tagNode name="mobile-config">
+ <properties>
+ <help>Generate QR code and movile configuration for Wireguard interface</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_interfaces.py --type wireguard</script>
+ </completionHelp>
+ </properties>
+ <children>
+ <tagNode name="server">
+ <properties>
+ <help>IP address or FQDN the client will connect to</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_local_ips.sh --both</script>
+ <list>&lt;hostname&gt;</list>
+ </completionHelp>
+ </properties>
+ <command>sudo ${vyos_op_scripts_dir}/wireguard_client.py --interface "$4" --server "$6"</command>
+ <children>
+ <tagNode name="address">
+ <properties>
+ <help>IPv4/IPv6 address used on the client side</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_local_ips.sh --both</script>
+ <list>&lt;hostname&gt;</list>
+ </completionHelp>
+ </properties>
+ <command>sudo ${vyos_op_scripts_dir}/wireguard_client.py --interface "$4" --server "$6" --address "$8"</command>
+ </tagNode>
+ </children>
+ </tagNode>
+ </children>
+ </tagNode>
</children>
</node>
</children>
@@ -73,7 +105,7 @@
<script>${vyos_completion_dir}/list_interfaces.py --type wireguard</script>
</completionHelp>
</properties>
- <command>sudo ${vyos_op_scripts_dir}/wireguard.py --showinterface "$4"</command>
+ <command>sudo ${vyos_op_scripts_dir}/wireguard.py --showinterface "$4"</command>
<children>
<leafNode name="allowed-ips">
<properties>
diff --git a/src/op_mode/wireguard_client.py b/src/op_mode/wireguard_client.py
new file mode 100755
index 000000000..b25aac2c8
--- /dev/null
+++ b/src/op_mode/wireguard_client.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2021 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import argparse
+import os
+
+from jinja2 import Template
+from ipaddress import ip_interface
+
+from vyos.template import is_ipv4
+from vyos.template import is_ipv6
+from vyos.util import cmd
+from vyos.util import popen
+
+if os.geteuid() != 0:
+ exit("You need to have root privileges to run this script.\nPlease try again, this time using 'sudo'. Exiting.")
+
+tmpl = """
+[Interface]
+PrivateKey = {{ privkey }}
+{% if address is defined and address|length > 0 %}
+Address = {{ address | join(', ')}}
+{% endif %}
+
+[Peer]
+PublicKey = {{ system_pubkey }}
+Endpoint = {{ server }}:{{ port }}
+AllowedIPs = 0.0.0.0/0, ::/0
+"""
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser()
+ parser.add_argument("-i", "--interface", type=str, help='WireGuard interface the client is connecting to', required=True)
+ parser.add_argument("-s", "--server", type=str, help='WireGuard server IPv4/IPv6 address or FQDN', required=True)
+ parser.add_argument("-a", "--address", type=str, help='WireGuard client IPv4/IPv6 address', action='append')
+ args = parser.parse_args()
+
+ interface = args.interface
+ wg_pubkey = cmd(f'wg show {interface} | grep "public key"').split(':')[-1].lstrip()
+ wg_port = cmd(f'wg show {interface} | grep "listening port"').split(':')[-1].lstrip()
+
+ # Generate WireGuard private key
+ privkey,_ = popen('wg genkey')
+ # Generate public key portion from given private key
+ pubkey,_ = popen('wg pubkey', input=privkey)
+
+ config = {
+ 'system_pubkey' : wg_pubkey,
+ 'privkey': privkey,
+ 'pubkey' : pubkey,
+ 'server' : args.server,
+ 'port' : wg_port,
+ 'address' : [],
+ }
+
+ if args.address:
+ v4_addr = 0
+ v6_addr = 0
+ for tmp in args.address:
+ try:
+ config['address'].append(str(ip_interface(tmp)))
+ if is_ipv4(tmp):
+ v4_addr += 1
+ elif is_ipv6(tmp):
+ v6_addr += 1
+ except:
+ print(tmp)
+ exit('Client IP address invalid!')
+
+ if (v4_addr > 1) or (v6_addr > 1):
+ exit('Client can only have one IPv4 and one IPv6 address.')
+
+ tmp = Template(tmpl, trim_blocks=True).render(config)
+ qrcode,err = popen('qrencode -t ansiutf8', input=tmp)
+
+ print(f'\nWireGuard client configuration for interface: {interface}')
+ print(tmp)
+ print('\n')
+ print(qrcode)