mirror of
https://github.com/Slava-Shchipunov/awg-openwrt.git
synced 2026-03-14 01:13:09 +00:00
feat: update luci awg
This commit is contained in:
@@ -1,17 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright (C) 2016 Dan Luedtke <mail@danrl.com>
|
|
||||||
#
|
|
||||||
# This is free software, licensed under the Apache License, Version 2.0 .
|
|
||||||
#
|
|
||||||
|
|
||||||
include $(TOPDIR)/rules.mk
|
|
||||||
|
|
||||||
LUCI_TITLE:=Support for AmneziaWG VPN
|
|
||||||
LUCI_DEPENDS:=+amneziawg-tools +ucode +qrencode
|
|
||||||
LUCI_PKGARCH:=all
|
|
||||||
|
|
||||||
PKG_PROVIDES:=luci-app-amneziawg
|
|
||||||
|
|
||||||
include $(TOPDIR)/feeds/luci/luci.mk
|
|
||||||
|
|
||||||
# call BuildPackage - OpenWrt buildroot signature
|
|
||||||
13
luci-proto-amneziawg/Makefile
Normal file
13
luci-proto-amneziawg/Makefile
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
|
LUCI_TITLE:=Support for AmneziaWG VPN
|
||||||
|
LUCI_DESCRIPTION:=Provides support and Web UI for AmneziaWG VPN
|
||||||
|
PKG_VERSION:=2.0.4
|
||||||
|
LUCI_DEPENDS:=+amneziawg-tools +ucode +luci-lib-uqr +resolveip
|
||||||
|
LUCI_PKGARCH:=all
|
||||||
|
|
||||||
|
PKG_LICENSE:=Apache-2.0
|
||||||
|
|
||||||
|
include $(TOPDIR)/feeds/luci/luci.mk
|
||||||
|
|
||||||
|
# call BuildPackage - OpenWrt buildroot signature
|
||||||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 38 KiB |
@@ -7,6 +7,7 @@
|
|||||||
'require form';
|
'require form';
|
||||||
'require network';
|
'require network';
|
||||||
'require validation';
|
'require validation';
|
||||||
|
'require uqr';
|
||||||
|
|
||||||
var generateKey = rpc.declare({
|
var generateKey = rpc.declare({
|
||||||
object: 'luci.amneziawg',
|
object: 'luci.amneziawg',
|
||||||
@@ -64,42 +65,16 @@ function generateDescription(name, texts) {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function invokeQREncode(data, div) {
|
function buildSVGQRCode(data, code) {
|
||||||
|
// pixel size larger than 4 clips right and bottom edges of complex configs
|
||||||
var code = div.children[0];
|
const options = {
|
||||||
var btn = div.children[1];
|
pixelSize: 4,
|
||||||
|
whiteColor: 'white',
|
||||||
dom.content(btn, [
|
blackColor: 'black'
|
||||||
E('a', {
|
};
|
||||||
'class': 'btn cbi-button-action',
|
const svg = uqr.renderSVG(data, options);
|
||||||
'style': 'text-align: center',
|
code.style.opacity = '';
|
||||||
'href': 'data:text/plain;charset=utf-8,' + encodeURIComponent(data),
|
dom.content(code, Object.assign(E(svg), { style: 'width:100%;height:auto' }));
|
||||||
'download': 'amneziawg.conf'
|
|
||||||
|
|
||||||
}, ['Download Configuration']),
|
|
||||||
]);
|
|
||||||
|
|
||||||
return fs.exec_direct('/usr/bin/qrencode', [
|
|
||||||
'--inline', '--8bit', '--type=SVG',
|
|
||||||
'--output=-', '--', data
|
|
||||||
]).then(function(svg) {
|
|
||||||
div.style.opacity = '';
|
|
||||||
dom.content(code, Object.assign(E(svg), { style: 'width:100%;height:auto' }));
|
|
||||||
}).catch(function(error) {
|
|
||||||
div.style.opacity = '';
|
|
||||||
|
|
||||||
if (L.isObject(error) && error.name == 'NotFoundError') {
|
|
||||||
dom.content(code, [
|
|
||||||
Object.assign(E(qrIcon), { style: 'width:32px;height:32px;opacity:.2' }),
|
|
||||||
E('p', _('The <em>qrencode</em> package is required for generating an QR code image of the configuration.'))
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
dom.content(code, [
|
|
||||||
_('Unable to generate QR code: %s').format(L.isObject(error) ? error.message : error)
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var cbiKeyPairGenerate = form.DummyValue.extend({
|
var cbiKeyPairGenerate = form.DummyValue.extend({
|
||||||
@@ -111,9 +86,6 @@ var cbiKeyPairGenerate = form.DummyValue.extend({
|
|||||||
pub = this.section.getUIElement(section_id, 'public_key'),
|
pub = this.section.getUIElement(section_id, 'public_key'),
|
||||||
map = this.map;
|
map = this.map;
|
||||||
|
|
||||||
if ((prv.getValue() || pub.getValue()) && !confirm(_('Do you want to replace the current keys?')))
|
|
||||||
return;
|
|
||||||
|
|
||||||
return generateKey().then(function(keypair) {
|
return generateKey().then(function(keypair) {
|
||||||
prv.setValue(keypair.priv);
|
prv.setValue(keypair.priv);
|
||||||
pub.setValue(keypair.pub);
|
pub.setValue(keypair.pub);
|
||||||
@@ -137,7 +109,7 @@ return network.registerProtocol('amneziawg', {
|
|||||||
return this._ubus('l3_device') || this.sid;
|
return this._ubus('l3_device') || this.sid;
|
||||||
},
|
},
|
||||||
|
|
||||||
getOpkgPackage: function() {
|
getPackageName: function() {
|
||||||
return 'amneziawg-tools';
|
return 'amneziawg-tools';
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -212,7 +184,7 @@ return network.registerProtocol('amneziawg', {
|
|||||||
o.placeholder = '1420';
|
o.placeholder = '1420';
|
||||||
o.optional = true;
|
o.optional = true;
|
||||||
|
|
||||||
o = s.taboption('advanced', form.Value, 'fwmark', _('Firewall Mark'), _('Optional. 32-bit mark for outgoing encrypted packets. Enter value in hex, starting with <code>0x</code>.'));
|
o = s.taboption('advanced', form.Value, 'fwmark', _('Firewall Mark'), _('Optional. 32-bit mark for packets during firewall processing. Enter value in hex, starting with <code>0x</code>.'));
|
||||||
o.optional = true;
|
o.optional = true;
|
||||||
o.validate = function(section_id, value) {
|
o.validate = function(section_id, value) {
|
||||||
if (value.length > 0 && !value.match(/^0x[a-fA-F0-9]{1,8}$/))
|
if (value.length > 0 && !value.match(/^0x[a-fA-F0-9]{1,8}$/))
|
||||||
@@ -224,62 +196,102 @@ return network.registerProtocol('amneziawg', {
|
|||||||
// AmneziaWG
|
// AmneziaWG
|
||||||
|
|
||||||
try {
|
try {
|
||||||
s.tab('amneziawg', _('AmneziaWG Settings'), _('Further information about AmneziaWG interfaces and peers at <a href=\'http://amnezia.org\'>amnezia.org</a>.'));
|
s.tab('amneziawg', _('AmneziaWG Settings'), _('Further information about AmneziaWG interfaces and peers at <a href=\'https://docs.amnezia.org/documentation/amnezia-wg\'>amnezia.org</a>.'));
|
||||||
}
|
}
|
||||||
catch(e) {}
|
catch(e) {}
|
||||||
|
|
||||||
o = s.taboption('amneziawg', form.Value, 'awg_jc', _('Jc'), _('Junk packet count.'));
|
o = s.taboption('amneziawg', form.Value, 'awg_jc', _('Jc'), _('Junk packet count.'));
|
||||||
o.datatype = 'uinteger';
|
o.datatype = 'uinteger';
|
||||||
|
o.placeholder = '0';
|
||||||
o.optional = true;
|
o.optional = true;
|
||||||
|
|
||||||
o = s.taboption('amneziawg', form.Value, 'awg_jmin', _('Jmin'), _('Junk packet minimum size.'));
|
o = s.taboption('amneziawg', form.Value, 'awg_jmin', _('Jmin'), _('Junk packet minimum size.'));
|
||||||
o.datatype = 'uinteger';
|
o.datatype = 'uinteger';
|
||||||
|
o.placeholder = '0';
|
||||||
o.optional = true;
|
o.optional = true;
|
||||||
|
|
||||||
o = s.taboption('amneziawg', form.Value, 'awg_jmax', _('Jmax'), _('Junk packet maximum size.'));
|
o = s.taboption('amneziawg', form.Value, 'awg_jmax', _('Jmax'), _('Junk packet maximum size.'));
|
||||||
o.datatype = 'uinteger';
|
o.datatype = 'uinteger';
|
||||||
|
o.placeholder = '0';
|
||||||
o.optional = true;
|
o.optional = true;
|
||||||
|
|
||||||
o = s.taboption('amneziawg', form.Value, 'awg_s1', _('S1'), _('Handshake initiation packet junk header size.'));
|
o = s.taboption('amneziawg', form.Value, 'awg_s1', _('S1'), _('Handshake initiation packet junk header size.'));
|
||||||
o.datatype = 'uinteger';
|
o.datatype = 'uinteger';
|
||||||
|
o.placeholder = '0';
|
||||||
o.optional = true;
|
o.optional = true;
|
||||||
|
|
||||||
o = s.taboption('amneziawg', form.Value, 'awg_s2', _('S2'), _('Handshake response packet junk header size.'));
|
o = s.taboption('amneziawg', form.Value, 'awg_s2', _('S2'), _('Handshake response packet junk header size.'));
|
||||||
o.datatype = 'uinteger';
|
o.datatype = 'uinteger';
|
||||||
|
o.placeholder = '0';
|
||||||
|
o.optional = true;
|
||||||
|
|
||||||
|
o = s.taboption('amneziawg', form.Value, 'awg_s3', _('S3'), _('Cookie reply packet junk header size.'));
|
||||||
|
o.datatype = 'uinteger';
|
||||||
|
o.placeholder = '0';
|
||||||
|
o.optional = true;
|
||||||
|
|
||||||
|
o = s.taboption('amneziawg', form.Value, 'awg_s4', _('S4'), _('Transport packet junk header size.'));
|
||||||
|
o.datatype = 'uinteger';
|
||||||
|
o.placeholder = '0';
|
||||||
o.optional = true;
|
o.optional = true;
|
||||||
|
|
||||||
o = s.taboption('amneziawg', form.Value, 'awg_h1', _('H1'), _('Handshake initiation packet type header.'));
|
o = s.taboption('amneziawg', form.Value, 'awg_h1', _('H1'), _('Handshake initiation packet type header.'));
|
||||||
o.datatype = 'uinteger';
|
o.datatype = 'string';
|
||||||
|
o.placeholder = '1';
|
||||||
o.optional = true;
|
o.optional = true;
|
||||||
|
|
||||||
o = s.taboption('amneziawg', form.Value, 'awg_h2', _('H2'), _('Handshake response packet type header.'));
|
o = s.taboption('amneziawg', form.Value, 'awg_h2', _('H2'), _('Handshake response packet type header.'));
|
||||||
o.datatype = 'uinteger';
|
o.datatype = 'string';
|
||||||
|
o.placeholder = '2';
|
||||||
o.optional = true;
|
o.optional = true;
|
||||||
|
|
||||||
o = s.taboption('amneziawg', form.Value, 'awg_h3', _('H3'), _('Handshake cookie packet type header.'));
|
o = s.taboption('amneziawg', form.Value, 'awg_h3', _('H3'), _('Handshake cookie packet type header.'));
|
||||||
o.datatype = 'uinteger';
|
o.datatype = 'string';
|
||||||
|
o.placeholder = '3';
|
||||||
o.optional = true;
|
o.optional = true;
|
||||||
|
|
||||||
o = s.taboption('amneziawg', form.Value, 'awg_h4', _('H4'), _('Transport packet type header.'));
|
o = s.taboption('amneziawg', form.Value, 'awg_h4', _('H4'), _('Transport packet type header.'));
|
||||||
o.datatype = 'uinteger';
|
o.datatype = 'string';
|
||||||
|
o.placeholder = '4';
|
||||||
|
o.optional = true;
|
||||||
|
|
||||||
|
o = s.taboption('amneziawg', form.Value, 'awg_i1', _('I1'), _('First special junk packet signature.'));
|
||||||
|
o.datatype = 'string';
|
||||||
|
o.optional = true;
|
||||||
|
|
||||||
|
o = s.taboption('amneziawg', form.Value, 'awg_i2', _('I2'), _('Second special junk packet signature.'));
|
||||||
|
o.datatype = 'string';
|
||||||
|
o.optional = true;
|
||||||
|
|
||||||
|
o = s.taboption('amneziawg', form.Value, 'awg_i3', _('I3'), _('Third special junk packet signature.'));
|
||||||
|
o.datatype = 'string';
|
||||||
|
o.optional = true;
|
||||||
|
|
||||||
|
o = s.taboption('amneziawg', form.Value, 'awg_i4', _('I4'), _('Fourth special junk packet signature.'));
|
||||||
|
o.datatype = 'string';
|
||||||
|
o.optional = true;
|
||||||
|
|
||||||
|
o = s.taboption('amneziawg', form.Value, 'awg_i5', _('I5'), _('Fifth special junk packet signature.'));
|
||||||
|
o.datatype = 'string';
|
||||||
o.optional = true;
|
o.optional = true;
|
||||||
|
|
||||||
// -- peers -----------------------------------------------------------------------
|
// -- peers -----------------------------------------------------------------------
|
||||||
|
|
||||||
try {
|
try {
|
||||||
s.tab('peers', _('Peers'), _('Further information about AmneziaWG interfaces and peers at <a href=\'http://amneziawg.com\'>amneziawg.com</a>.'));
|
s.tab('peers', _('Peers'), _('Further information about AmneziaWG interfaces and peers at <a href=\'https://docs.amnezia.org/documentation/amnezia-wg\'>amnezia.org</a>.'));
|
||||||
}
|
}
|
||||||
catch(e) {}
|
catch(e) {}
|
||||||
|
|
||||||
o = s.taboption('peers', form.SectionValue, '_peers', form.GridSection, 'amneziawg_%s'.format(s.section));
|
o = s.taboption('peers', form.SectionValue, '_peers', form.GridSection, 'amneziawg_%s'.format(s.section));
|
||||||
o.depends('proto', 'amneziawg');
|
o.depends('proto', 'amneziawg');
|
||||||
|
|
||||||
ss = o.subsection;
|
ss = o.subsection;
|
||||||
ss.anonymous = true;
|
ss.anonymous = true;
|
||||||
ss.addremove = true;
|
ss.addremove = true;
|
||||||
ss.addbtntitle = _('Add peer');
|
ss.addbtntitle = _('Add peer');
|
||||||
ss.nodescriptions = true;
|
ss.nodescriptions = true;
|
||||||
ss.modaltitle = _('Edit peer');
|
ss.modaltitle = _('Edit peer');
|
||||||
|
ss.sortable = true;
|
||||||
|
|
||||||
ss.handleDragConfig = function(ev) {
|
ss.handleDragConfig = function(ev) {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
@@ -416,15 +428,22 @@ return network.registerProtocol('amneziawg', {
|
|||||||
s.getOption('public_key').getUIElement(s.section).setValue(keypair.pub);
|
s.getOption('public_key').getUIElement(s.section).setValue(keypair.pub);
|
||||||
s.getOption('listen_port').getUIElement(s.section).setValue(config.interface_listenport || '');
|
s.getOption('listen_port').getUIElement(s.section).setValue(config.interface_listenport || '');
|
||||||
s.getOption('addresses').getUIElement(s.section).setValue(config.interface_address);
|
s.getOption('addresses').getUIElement(s.section).setValue(config.interface_address);
|
||||||
s.getOption('awg_jc').getUIElement(s.section).setValue(config.interface_jc);
|
s.getOption('awg_jc').getUIElement(s.section).setValue(config.interface_jc || '');
|
||||||
s.getOption('awg_jmin').getUIElement(s.section).setValue(config.interface_jmin);
|
s.getOption('awg_jmin').getUIElement(s.section).setValue(config.interface_jmin || '');
|
||||||
s.getOption('awg_jmax').getUIElement(s.section).setValue(config.interface_jmax);
|
s.getOption('awg_jmax').getUIElement(s.section).setValue(config.interface_jmax || '');
|
||||||
s.getOption('awg_s1').getUIElement(s.section).setValue(config.interface_s1);
|
s.getOption('awg_s1').getUIElement(s.section).setValue(config.interface_s1 || '');
|
||||||
s.getOption('awg_s2').getUIElement(s.section).setValue(config.interface_s2);
|
s.getOption('awg_s2').getUIElement(s.section).setValue(config.interface_s2 || '');
|
||||||
s.getOption('awg_h1').getUIElement(s.section).setValue(config.interface_h1);
|
s.getOption('awg_s3').getUIElement(s.section).setValue(config.interface_s3 || '');
|
||||||
s.getOption('awg_h2').getUIElement(s.section).setValue(config.interface_h2);
|
s.getOption('awg_s4').getUIElement(s.section).setValue(config.interface_s4 || '');
|
||||||
s.getOption('awg_h3').getUIElement(s.section).setValue(config.interface_h3);
|
s.getOption('awg_h1').getUIElement(s.section).setValue(config.interface_h1 || '');
|
||||||
s.getOption('awg_h4').getUIElement(s.section).setValue(config.interface_h4);
|
s.getOption('awg_h2').getUIElement(s.section).setValue(config.interface_h2 || '');
|
||||||
|
s.getOption('awg_h3').getUIElement(s.section).setValue(config.interface_h3 || '');
|
||||||
|
s.getOption('awg_h4').getUIElement(s.section).setValue(config.interface_h4 || '');
|
||||||
|
s.getOption('awg_i1').getUIElement(s.section).setValue(config.interface_i1 || '');
|
||||||
|
s.getOption('awg_i2').getUIElement(s.section).setValue(config.interface_i2 || '');
|
||||||
|
s.getOption('awg_i3').getUIElement(s.section).setValue(config.interface_i3 || '');
|
||||||
|
s.getOption('awg_i4').getUIElement(s.section).setValue(config.interface_i4 || '');
|
||||||
|
s.getOption('awg_i5').getUIElement(s.section).setValue(config.interface_i5 || '');
|
||||||
|
|
||||||
if (config.interface_dns)
|
if (config.interface_dns)
|
||||||
s.getOption('dns').getUIElement(s.section).setValue(config.interface_dns);
|
s.getOption('dns').getUIElement(s.section).setValue(config.interface_dns);
|
||||||
@@ -500,7 +519,7 @@ return network.registerProtocol('amneziawg', {
|
|||||||
E('p', _('Drag or paste a valid <em>*.conf</em> file below to configure the local AmneziaWG interface.'))
|
E('p', _('Drag or paste a valid <em>*.conf</em> file below to configure the local AmneziaWG interface.'))
|
||||||
] : [
|
] : [
|
||||||
E('p', _('Paste or drag a AmneziaWG configuration (commonly <em>wg0.conf</em>) from another system below to create a matching peer entry allowing that system to connect to the local AmneziaWG interface.')),
|
E('p', _('Paste or drag a AmneziaWG configuration (commonly <em>wg0.conf</em>) from another system below to create a matching peer entry allowing that system to connect to the local AmneziaWG interface.')),
|
||||||
E('p', _('To fully configure the local AmneziaWG interface from an existing (e.g. provider supplied) configuration file, use the <strong><a class="full-import" href="#">configuration import</a></strong> instead.'))
|
E('p', _('To configure fully the local AmneziaWG interface from an existing (e.g. provider supplied) configuration file, use the <strong><a class="full-import" href="#">configuration import</a></strong> instead.'))
|
||||||
]),
|
]),
|
||||||
E('p', [
|
E('p', [
|
||||||
E('textarea', {
|
E('textarea', {
|
||||||
@@ -575,9 +594,10 @@ return network.registerProtocol('amneziawg', {
|
|||||||
return E('em', _('No peers defined yet.'));
|
return E('em', _('No peers defined yet.'));
|
||||||
};
|
};
|
||||||
|
|
||||||
o = ss.option(form.Flag, 'disabled', _('Peer disabled'), _('Enable / Disable peer. Restart amneziawg interface to apply changes.'));
|
o = ss.option(form.Flag, 'disabled', _('Disabled'), _('Enable / Disable peer. Restart amneziawg interface to apply changes.'));
|
||||||
o.modalonly = true;
|
o.editable = true;
|
||||||
o.optional = true;
|
o.optional = true;
|
||||||
|
o.width = '5%';
|
||||||
|
|
||||||
o = ss.option(form.Value, 'description', _('Description'), _('Optional. Description of peer.'));
|
o = ss.option(form.Value, 'description', _('Description'), _('Optional. Description of peer.'));
|
||||||
o.placeholder = 'My Peer';
|
o.placeholder = 'My Peer';
|
||||||
@@ -675,9 +695,6 @@ return network.registerProtocol('amneziawg', {
|
|||||||
var psk = this.section.getUIElement(section_id, 'preshared_key'),
|
var psk = this.section.getUIElement(section_id, 'preshared_key'),
|
||||||
map = this.map;
|
map = this.map;
|
||||||
|
|
||||||
if (psk.getValue() && !confirm(_('Do you want to replace the current PSK?')))
|
|
||||||
return;
|
|
||||||
|
|
||||||
return generatePsk().then(function(key) {
|
return generatePsk().then(function(key) {
|
||||||
psk.setValue(key);
|
psk.setValue(key);
|
||||||
map.save(null, true);
|
map.save(null, true);
|
||||||
@@ -757,69 +774,78 @@ return network.registerProtocol('amneziawg', {
|
|||||||
|
|
||||||
o.modalonly = true;
|
o.modalonly = true;
|
||||||
|
|
||||||
o.createPeerConfig = function (section_id, endpoint, ips, eips, dns) {
|
o.createPeerConfig = function(section_id, endpoint, ips, eips, dns) {
|
||||||
var pub = s.formvalue(s.section, 'public_key'),
|
var pub = s.formvalue(s.section, 'public_key'),
|
||||||
port = s.formvalue(s.section, 'listen_port') || '51820',
|
port = s.formvalue(s.section, 'listen_port') || '51820',
|
||||||
prv = this.section.formvalue(section_id, 'private_key'),
|
jc = s.formvalue(s.section, 'awg_jc'),
|
||||||
psk = this.section.formvalue(section_id, 'preshared_key'),
|
jmin = s.formvalue(s.section, 'awg_jmin'),
|
||||||
eport = this.section.formvalue(section_id, 'endpoint_port'),
|
jmax = s.formvalue(s.section, 'awg_jmax'),
|
||||||
keep = this.section.formvalue(section_id, 'persistent_keepalive'),
|
s1 = s.formvalue(s.section, 'awg_s1'),
|
||||||
jc = s.formvalue(s.section, 'awg_jc'),
|
s2 = s.formvalue(s.section, 'awg_s2'),
|
||||||
jmin = s.formvalue(s.section, 'awg_jmin'),
|
s3 = s.formvalue(s.section, 'awg_s3'),
|
||||||
jmax = s.formvalue(s.section, 'awg_jmax'),
|
s4 = s.formvalue(s.section, 'awg_s4'),
|
||||||
s1 = s.formvalue(s.section, 'awg_s1'),
|
h1 = s.formvalue(s.section, 'awg_h1'),
|
||||||
s2 = s.formvalue(s.section, 'awg_s2'),
|
h2 = s.formvalue(s.section, 'awg_h2'),
|
||||||
h1 = s.formvalue(s.section, 'awg_h1'),
|
h3 = s.formvalue(s.section, 'awg_h3'),
|
||||||
h2 = s.formvalue(s.section, 'awg_h2'),
|
h4 = s.formvalue(s.section, 'awg_h4'),
|
||||||
h3 = s.formvalue(s.section, 'awg_h3'),
|
i1 = s.formvalue(s.section, 'awg_i1'),
|
||||||
h4 = s.formvalue(s.section, 'awg_h4');
|
i2 = s.formvalue(s.section, 'awg_i2'),
|
||||||
|
i3 = s.formvalue(s.section, 'awg_i3'),
|
||||||
|
i4 = s.formvalue(s.section, 'awg_i4'),
|
||||||
|
i5 = s.formvalue(s.section, 'awg_i5'),
|
||||||
|
prv = this.section.formvalue(section_id, 'private_key'),
|
||||||
|
psk = this.section.formvalue(section_id, 'preshared_key'),
|
||||||
|
eport = this.section.formvalue(section_id, 'endpoint_port'),
|
||||||
|
keep = this.section.formvalue(section_id, 'persistent_keepalive');
|
||||||
|
|
||||||
|
// If endpoint is IPv6 we must escape it with []
|
||||||
if (endpoint.indexOf(':') > 0) {
|
if (endpoint.indexOf(':') > 0) {
|
||||||
endpoint = '[' + endpoint + ']';
|
endpoint = '['+endpoint+']';
|
||||||
}
|
}
|
||||||
var configLines = [
|
|
||||||
|
return [
|
||||||
'[Interface]',
|
'[Interface]',
|
||||||
'PrivateKey = ' + prv,
|
'PrivateKey = ' + prv,
|
||||||
eport ? 'ListenPort = ' + eport : '# ListenPort not defined',
|
|
||||||
eips && eips.length ? 'Address = ' + eips.join(', ') : '# Address not defined',
|
eips && eips.length ? 'Address = ' + eips.join(', ') : '# Address not defined',
|
||||||
|
eport ? 'ListenPort = ' + eport : '# ListenPort not defined',
|
||||||
dns && dns.length ? 'DNS = ' + dns.join(', ') : '# DNS not defined',
|
dns && dns.length ? 'DNS = ' + dns.join(', ') : '# DNS not defined',
|
||||||
''
|
jc ? 'Jc = ' + jc : '# Jc not defined',
|
||||||
];
|
jmin ? 'Jmin = ' + jmin : '# Jmin not defined',
|
||||||
|
jmax ? 'Jmax = ' + jmax : '# Jmax not defined',
|
||||||
if (jc) configLines.push('jc = ' + jc);
|
s1 ? 'S1 = ' + s1 : '# S1 not defined',
|
||||||
if (jmin) configLines.push('jmin = ' + jmin);
|
s2 ? 'S2 = ' + s2 : '# S2 not defined',
|
||||||
if (jmax) configLines.push('jmax = ' + jmax);
|
s3 ? 'S3 = ' + s3 : '# S3 not defined',
|
||||||
if (s1) configLines.push('s1 = ' + s1);
|
s4 ? 'S4 = ' + s4 : '# S4 not defined',
|
||||||
if (s2) configLines.push('s2 = ' + s2);
|
h1 ? 'H1 = ' + h1 : '# H1 not defined',
|
||||||
if (h1) configLines.push('h1 = ' + h1);
|
h2 ? 'H2 = ' + h2 : '# H2 not defined',
|
||||||
if (h2) configLines.push('h2 = ' + h2);
|
h3 ? 'H3 = ' + h3 : '# H3 not defined',
|
||||||
if (h3) configLines.push('h3 = ' + h3);
|
h4 ? 'H4 = ' + h4 : '# H4 not defined',
|
||||||
if (h4) configLines.push('h4 = ' + h4);
|
i1 ? 'I1 = ' + i1 : '# I1 not defined',
|
||||||
|
i2 ? 'I2 = ' + i2 : '# I2 not defined',
|
||||||
configLines.push(
|
i3 ? 'I3 = ' + i3 : '# I3 not defined',
|
||||||
|
i4 ? 'I4 = ' + i4 : '# I4 not defined',
|
||||||
|
i5 ? 'I5 = ' + i5 : '# I5 not defined',
|
||||||
'',
|
'',
|
||||||
'[Peer]',
|
'[Peer]',
|
||||||
'PublicKey = ' + pub,
|
'PublicKey = ' + pub,
|
||||||
psk ? 'PresharedKey = ' + psk : '# PresharedKey not used',
|
psk ? 'PresharedKey = ' + psk : '# PresharedKey not used',
|
||||||
ips && ips.length ? 'AllowedIPs = ' + ips.join(', ') : '# AllowedIPs not defined',
|
ips && ips.length ? 'AllowedIPs = ' + ips.join(', ') : '# AllowedIPs not defined',
|
||||||
endpoint ? 'Endpoint = ' + endpoint + ':' + port : '# Endpoint not defined',
|
endpoint ? 'Endpoint = ' + endpoint + ':' + port : '# Endpoint not defined',
|
||||||
keep ? 'PersistentKeepAlive = ' + keep : '# PersistentKeepAlive not defined',
|
keep ? 'PersistentKeepAlive = ' + keep : '# PersistentKeepAlive not defined'
|
||||||
''
|
].join('\n');
|
||||||
);
|
};
|
||||||
|
|
||||||
return configLines.join('\n');
|
|
||||||
};
|
|
||||||
|
|
||||||
o.handleGenerateQR = function(section_id, ev) {
|
o.handleGenerateQR = function(section_id, ev) {
|
||||||
var mapNode = ss.getActiveModalMap(),
|
var mapNode = ss.getActiveModalMap(),
|
||||||
headNode = mapNode.parentNode.querySelector('h4'),
|
headNode = mapNode.parentNode.querySelector('h4'),
|
||||||
configGenerator = this.createPeerConfig.bind(this, section_id),
|
configGenerator = this.createPeerConfig.bind(this, section_id),
|
||||||
parent = this.map,
|
parent = this.map,
|
||||||
eips = this.section.formvalue(section_id, 'allowed_ips');
|
eips = this.section.formvalue(section_id, 'allowed_ips');
|
||||||
|
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
network.getWANNetworks(),
|
network.getWANNetworks(),
|
||||||
network.getWAN6Networks(),
|
network.getWAN6Networks(),
|
||||||
|
network.getNetwork('lan'),
|
||||||
L.resolveDefault(uci.load('ddns')),
|
L.resolveDefault(uci.load('ddns')),
|
||||||
L.resolveDefault(uci.load('system')),
|
L.resolveDefault(uci.load('system')),
|
||||||
parent.save(null, true)
|
parent.save(null, true)
|
||||||
@@ -827,12 +853,12 @@ return network.registerProtocol('amneziawg', {
|
|||||||
var hostnames = [];
|
var hostnames = [];
|
||||||
|
|
||||||
uci.sections('ddns', 'service', function(s) {
|
uci.sections('ddns', 'service', function(s) {
|
||||||
if (typeof(s.lookup_host) == 'string' && s.enabled == '1')
|
if (typeof(s?.lookup_host) == 'string' && s?.enabled == '1')
|
||||||
hostnames.push(s.lookup_host);
|
hostnames.push(s.lookup_host);
|
||||||
});
|
});
|
||||||
|
|
||||||
uci.sections('system', 'system', function(s) {
|
uci.sections('system', 'system', function(s) {
|
||||||
if (typeof(s.hostname) == 'string' && s.hostname.indexOf('.') > 0)
|
if (typeof(s?.hostname) == 'string' && s?.hostname?.indexOf('.') > 0)
|
||||||
hostnames.push(s.hostname);
|
hostnames.push(s.hostname);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -846,34 +872,34 @@ return network.registerProtocol('amneziawg', {
|
|||||||
|
|
||||||
var dns = [];
|
var dns = [];
|
||||||
|
|
||||||
|
var lan = data[2];
|
||||||
|
if (lan) {
|
||||||
|
var lanIp = lan.getIPAddr();
|
||||||
|
if (lanIp) {
|
||||||
|
dns.unshift(lanIp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var qrm, qrs, qro;
|
var qrm, qrs, qro;
|
||||||
|
|
||||||
qrm = new form.JSONMap({
|
qrm = new form.JSONMap({ config: { endpoint: hostnames[0], allowed_ips: ips, addresses: eips, dns_servers: dns } }, null, _('The generated configuration can be imported into a WireGuard client application to set up a connection towards this device.'));
|
||||||
config: {
|
|
||||||
endpoint: hostnames[0],
|
|
||||||
allowed_ips: ips,
|
|
||||||
addresses: eips,
|
|
||||||
dns_servers: dns
|
|
||||||
}
|
|
||||||
}, null, _('The generated configuration can be imported into a AmneziaWG client application to set up a connection towards this device.'));
|
|
||||||
|
|
||||||
qrm.parent = parent;
|
qrm.parent = parent;
|
||||||
|
|
||||||
qrs = qrm.section(form.NamedSection, 'config');
|
qrs = qrm.section(form.NamedSection, 'config');
|
||||||
|
|
||||||
function handleConfigChange(ev, section_id, value) {
|
function handleConfigChange(ev, section_id, value) {
|
||||||
var code = this.map.findElement('.qr-code'),
|
var code = this.map.findElement('.qr-code'),
|
||||||
conf = this.map.findElement('.client-config'),
|
conf = this.map.findElement('.client-config'),
|
||||||
endpoint = this.section.getUIElement(section_id, 'endpoint'),
|
endpoint = this.section.getUIElement(section_id, 'endpoint'),
|
||||||
ips = this.section.getUIElement(section_id, 'allowed_ips');
|
ips = this.section.getUIElement(section_id, 'allowed_ips');
|
||||||
eips = this.section.getUIElement(section_id, 'addresses');
|
eips = this.section.getUIElement(section_id, 'addresses');
|
||||||
dns = this.section.getUIElement(section_id, 'dns_servers');
|
dns = this.section.getUIElement(section_id, 'dns_servers');
|
||||||
|
|
||||||
if (this.isValid(section_id)) {
|
if (this.isValid(section_id)) {
|
||||||
conf.firstChild.data = configGenerator(endpoint.getValue(), ips.getValue(), eips.getValue(), dns.getValue());
|
conf.firstChild.data = configGenerator(endpoint.getValue(), ips.getValue(), eips.getValue(), dns.getValue());
|
||||||
code.style.opacity = '.5';
|
code.style.opacity = '.5';
|
||||||
|
|
||||||
invokeQREncode(conf.firstChild.data, code);
|
buildSVGQRCode(conf.firstChild.data, code);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -897,7 +923,7 @@ return network.registerProtocol('amneziawg', {
|
|||||||
qro.datatype = 'ipaddr';
|
qro.datatype = 'ipaddr';
|
||||||
qro.default = eips;
|
qro.default = eips;
|
||||||
eips.forEach(function(eip) { qro.value(eip) });
|
eips.forEach(function(eip) { qro.value(eip) });
|
||||||
qro.onchange = handleConfigChange;
|
qro.onchange = handleConfigChange;
|
||||||
|
|
||||||
qro = qrs.option(form.DummyValue, 'output');
|
qro = qrs.option(form.DummyValue, 'output');
|
||||||
qro.renderWidget = function() {
|
qro.renderWidget = function() {
|
||||||
@@ -908,16 +934,9 @@ return network.registerProtocol('amneziawg', {
|
|||||||
}, [
|
}, [
|
||||||
E('div', {
|
E('div', {
|
||||||
'class': 'qr-code',
|
'class': 'qr-code',
|
||||||
'style': 'display:flex; flex-direction: column; text-align: center',
|
'style': 'width:320px;flex:0 1 320px;text-align:center'
|
||||||
}, [
|
}, [
|
||||||
E('div', {
|
E('em', { 'class': 'spinning' }, [ _('Generating QR code…') ])
|
||||||
'style': 'width:320px;flex:0 1 320px;text-align:center'
|
|
||||||
}, [
|
|
||||||
E('em', { 'class': 'spinning' }, [ _('Generating QR code…') ])
|
|
||||||
]),
|
|
||||||
|
|
||||||
E('div', {
|
|
||||||
}, ['Download Configuration']),
|
|
||||||
]),
|
]),
|
||||||
E('pre', {
|
E('pre', {
|
||||||
'class': 'client-config',
|
'class': 'client-config',
|
||||||
@@ -934,7 +953,7 @@ return network.registerProtocol('amneziawg', {
|
|||||||
}, [ peer_config ])
|
}, [ peer_config ])
|
||||||
]);
|
]);
|
||||||
|
|
||||||
invokeQREncode(peer_config, node.firstChild);
|
buildSVGQRCode(peer_config, node.firstChild);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
};
|
};
|
||||||
@@ -6,9 +6,9 @@
|
|||||||
'require ui';
|
'require ui';
|
||||||
|
|
||||||
|
|
||||||
var callGetWgInstances = rpc.declare({
|
var callgetAwgInstances = rpc.declare({
|
||||||
object: 'luci.amneziawg',
|
object: 'luci.amneziawg',
|
||||||
method: 'getWgInstances'
|
method: 'getAwgInstances'
|
||||||
});
|
});
|
||||||
|
|
||||||
function timestampToStr(timestamp) {
|
function timestampToStr(timestamp) {
|
||||||
@@ -128,7 +128,7 @@ return view.extend({
|
|||||||
'click': ui.createHandlerFn(this, handleInterfaceDetails, ifaces[instanceName])
|
'click': ui.createHandlerFn(this, handleInterfaceDetails, ifaces[instanceName])
|
||||||
}, [
|
}, [
|
||||||
E('span', { 'class': 'ifacebadge' }, [
|
E('span', { 'class': 'ifacebadge' }, [
|
||||||
E('img', { 'src': L.resource('icons', 'tunnel.svg') }),
|
E('img', { 'src': L.resource('icons', 'amneziawg.svg') }),
|
||||||
'\xa0',
|
'\xa0',
|
||||||
instanceName
|
instanceName
|
||||||
]),
|
]),
|
||||||
@@ -153,7 +153,7 @@ return view.extend({
|
|||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
poll.add(L.bind(function () {
|
poll.add(L.bind(function () {
|
||||||
return callGetWgInstances().then(L.bind(function(ifaces) {
|
return callgetAwgInstances().then(L.bind(function(ifaces) {
|
||||||
dom.content(
|
dom.content(
|
||||||
document.querySelector('#view'),
|
document.querySelector('#view'),
|
||||||
this.renderIfaces(ifaces)
|
this.renderIfaces(ifaces)
|
||||||
158
luci-proto-amneziawg/po/ru/amneziawg.po
Normal file
158
luci-proto-amneziawg/po/ru/amneziawg.po
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
msgid "Imports settings from an existing AmneziaWG configuration file"
|
||||||
|
msgstr "Импортирует настройки из существующего файла конфигурации AmneziaWG"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Drag or paste a valid <em>*.conf</em> file below to configure the local "
|
||||||
|
"AmneziaWG interface."
|
||||||
|
msgstr ""
|
||||||
|
"Перетащите или вставьте правильный файл <em>*.conf</em> ниже, чтобы "
|
||||||
|
"настроить локальный интерфейс AmneziaWG."
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Paste or drag a AmneziaWG configuration (commonly <em>wg0.conf</em>) from "
|
||||||
|
"another system below to create a matching peer entry allowing that system to "
|
||||||
|
"connect to the local AmneziaWG interface."
|
||||||
|
msgstr ""
|
||||||
|
"Вставьте или перетащите конфигурацию AmneziaWG (обычно <em>wg0.conf</em>) из "
|
||||||
|
"другой системы ниже, чтобы создать соответствующую запись узла, позволяющую "
|
||||||
|
"этой системе подключиться к локальному интерфейсу AmneziaWG."
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"To configure fully the local AmneziaWG interface from an existing (e.g. "
|
||||||
|
"provider supplied) configuration file, use the <strong><a class=\"full-"
|
||||||
|
"import\" href=\"#\">configuration import</a></strong> instead."
|
||||||
|
msgstr ""
|
||||||
|
"Чтобы полностью настроить локальный интерфейс AmneziaWG из существующего "
|
||||||
|
"(например, предоставленного провайдером) файла конфигурации, используйте "
|
||||||
|
"вместо этого <strong><a class=\"full-import\" href=\"#\">импорт "
|
||||||
|
"конфигурации</a></strong>."
|
||||||
|
|
||||||
|
msgid "Paste or drag supplied AmneziaWG configuration file…"
|
||||||
|
msgstr "Вставьте или перетащите имеющийся файл конфигурации AmneziaWG…"
|
||||||
|
|
||||||
|
msgid "Paste or drag AmneziaWG peer configuration (wg0.conf) file…"
|
||||||
|
msgstr "Вставьте или перетащите файл конфигурации узлов AmneziaWG (wg0.conf)…"
|
||||||
|
|
||||||
|
msgid "Recommended. IP addresses of the AmneziaWG interface."
|
||||||
|
msgstr "Рекомендуемый. IP адреса интерфейса AmneziaWG."
|
||||||
|
|
||||||
|
msgid "Imports settings from an existing AmneziaWG configuration file"
|
||||||
|
msgstr "Импортирует настройки из существующего файла конфигурации AmneziaWG"
|
||||||
|
|
||||||
|
msgid "AmneziaWG Settings"
|
||||||
|
msgstr "Настройки AmneziaWG"
|
||||||
|
|
||||||
|
msgid "Imports settings from an existing AmneziaWG configuration file"
|
||||||
|
msgstr "Импортирует настройки из существующего файла конфигурации AmneziaWG"
|
||||||
|
|
||||||
|
msgid "Imports settings from an existing AmneziaWG configuration file"
|
||||||
|
msgstr "Импортирует настройки из существующего файла конфигурации AmneziaWG"
|
||||||
|
|
||||||
|
msgid "Imports settings from an existing AmneziaWG configuration file"
|
||||||
|
msgstr "Импортирует настройки из существующего файла конфигурации AmneziaWG"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Further information about AmneziaWG interfaces and peers at <a href='https://"
|
||||||
|
"docs.amnezia.org/documentation/amnezia-wg'>amnezia.org</a>."
|
||||||
|
msgstr ""
|
||||||
|
"Дополнительная информация об AmneziaWG интерфейсах и узлах приведена по "
|
||||||
|
"адресу <a href='https://docs.amnezia.org/documentation/amnezia-wg'>amnezia.org</a>."
|
||||||
|
|
||||||
|
msgid "Junk packet count."
|
||||||
|
msgstr "Количество мусорных пакетов."
|
||||||
|
|
||||||
|
msgid "Junk packet minimum size."
|
||||||
|
msgstr "Минимальный размер мусорного пакета."
|
||||||
|
|
||||||
|
msgid "Junk packet maximum size."
|
||||||
|
msgstr "Максимальный размер мусорного пакета."
|
||||||
|
|
||||||
|
msgid "Handshake initiation packet junk header size."
|
||||||
|
msgstr "Размер мусорного заголовка пакета инициации рукопожатия."
|
||||||
|
|
||||||
|
msgid "Handshake response packet junk header size."
|
||||||
|
msgstr "Размер мусорного заголовка пакета ответа на рукопожатие."
|
||||||
|
|
||||||
|
msgid "Cookie reply packet junk header size."
|
||||||
|
msgstr "Размер мусорного заголовка пакета ответа cookie."
|
||||||
|
|
||||||
|
msgid "Transport packet junk header size."
|
||||||
|
msgstr "Размер мусорного заголовка транспортного пакета."
|
||||||
|
|
||||||
|
msgid "Handshake initiation packet type header."
|
||||||
|
msgstr "Тип заголовка пакета инициации рукопожатия."
|
||||||
|
|
||||||
|
msgid "Handshake response packet type header."
|
||||||
|
msgstr "Тип заголовка пакета ответа на рукопожатие."
|
||||||
|
|
||||||
|
msgid "Handshake cookie packet type header."
|
||||||
|
msgstr "Тип заголовка пакета под нагрузкой."
|
||||||
|
|
||||||
|
msgid "Transport packet type header."
|
||||||
|
msgstr "Тип заголовка транспортного пакета."
|
||||||
|
|
||||||
|
msgid "First special junk packet signature."
|
||||||
|
msgstr "Сигнатура первого special junk пакета."
|
||||||
|
|
||||||
|
msgid "Second special junk packet signature."
|
||||||
|
msgstr "Сигнатура второго special junk пакета."
|
||||||
|
|
||||||
|
msgid "Third special junk packet signature."
|
||||||
|
msgstr "Сигнатура третьего special junk пакета."
|
||||||
|
|
||||||
|
msgid "Fourth special junk packet signature."
|
||||||
|
msgstr "Сигнатура четвертого special junk пакета."
|
||||||
|
|
||||||
|
msgid "Fifth special junk packet signature."
|
||||||
|
msgstr "Сигнатура пятого special junk пакета."
|
||||||
|
|
||||||
|
msgid "Enable / Disable peer. Restart amneziawg interface to apply changes."
|
||||||
|
msgstr ""
|
||||||
|
"Включить/выключить узел. Перезапустите интерфейс AmneziaWG, чтобы применить "
|
||||||
|
"изменения."
|
||||||
|
|
||||||
|
msgid "AmneziaWG peer is disabled"
|
||||||
|
msgstr "Узел AmneziaWG отключён"
|
||||||
|
|
||||||
|
msgctxt "Label indicating that AmneziaWG peer is disabled"
|
||||||
|
msgid "Disabled"
|
||||||
|
msgstr "Отключено"
|
||||||
|
|
||||||
|
msgctxt "Label indicating that AmneziaWG peer lacks public key"
|
||||||
|
msgid "Key missing"
|
||||||
|
msgstr "Отсутствует ключ"
|
||||||
|
|
||||||
|
msgctxt "Tooltip displaying full AmneziaWG peer public key"
|
||||||
|
msgid "Public key: %h"
|
||||||
|
msgstr "Публичный ключ: %h"
|
||||||
|
|
||||||
|
msgctxt "Label indicating that AmneziaWG peer private key is stored"
|
||||||
|
msgid "Private"
|
||||||
|
msgstr "Private"
|
||||||
|
|
||||||
|
msgctxt "Label indicating that AmneziaWG peer uses a PSK"
|
||||||
|
msgid "PSK"
|
||||||
|
msgstr "PSK"
|
||||||
|
|
||||||
|
msgid "Required. Public key of the AmneziaWG peer."
|
||||||
|
msgstr "Обязательно. Публичный ключ AmneziaWG узла."
|
||||||
|
|
||||||
|
"Optional. Private key of the AmneziaWG peer. The key is not required for "
|
||||||
|
"establishing a connection but allows generating a peer configuration or QR "
|
||||||
|
"code if available. It can be removed after the configuration has been "
|
||||||
|
"exported."
|
||||||
|
msgstr ""
|
||||||
|
"Необязательно. Закрытый ключ узла AmneziaWG. Ключ не требуется для "
|
||||||
|
"установления соединения, но позволяет сгенерировать конфигурацию узла или QR-"
|
||||||
|
"код, если он доступен. Он может быть удален после экспорта конфигурации."
|
||||||
|
|
||||||
|
msgid "Generates a configuration suitable for import on a AmneziaWG peer"
|
||||||
|
msgstr "Создает конфигурацию, подходящую для импорта на узле AmneziaWG"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"No fixed interface listening port defined, peers might not be able to "
|
||||||
|
"initiate connections to this AmneziaWG instance!"
|
||||||
|
msgstr ""
|
||||||
|
"Не определен фиксированный порт прослушивания интерфейса, поэтому узлы могут "
|
||||||
|
"оказаться не в состоянии инициировать соединения с этим экземпляром "
|
||||||
|
"AmneziaWG!"
|
||||||
25
luci-proto-amneziawg/po/ru/status.po
Normal file
25
luci-proto-amneziawg/po/ru/status.po
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
msgid "AmneziaWG Status"
|
||||||
|
msgstr "Состояние AmneziaWG"
|
||||||
|
|
||||||
|
msgctxt "AmneziaWG instance heading"
|
||||||
|
msgid "Instance \"%h\""
|
||||||
|
msgstr "Экземпляр «%h»"
|
||||||
|
|
||||||
|
msgctxt "No AmneziaWG peer handshake yet"
|
||||||
|
msgid "Never"
|
||||||
|
msgstr "Никогда"
|
||||||
|
|
||||||
|
msgctxt "AmneziaWG keep alive interval"
|
||||||
|
msgid "every %ds"
|
||||||
|
msgstr "каждые %dс"
|
||||||
|
|
||||||
|
msgctxt "Tooltip displaying full AmneziaWG peer public key"
|
||||||
|
msgid "Public key: %h"
|
||||||
|
msgstr "Публичный ключ: %h"
|
||||||
|
|
||||||
|
msgctxt "AmneziaWG listen port"
|
||||||
|
msgid "Port %d"
|
||||||
|
msgstr "Порт %d"
|
||||||
|
|
||||||
|
msgid "No AmneziaWG interfaces configured."
|
||||||
|
msgstr "Интерфейсы AmneziaWG не настроены."
|
||||||
@@ -2,15 +2,12 @@
|
|||||||
"luci-proto-amneziawg": {
|
"luci-proto-amneziawg": {
|
||||||
"description": "Grant access to LuCI AmneziaWG procedures",
|
"description": "Grant access to LuCI AmneziaWG procedures",
|
||||||
"read": {
|
"read": {
|
||||||
"file": {
|
|
||||||
"/usr/bin/qrencode --inline --8bit --type=SVG --output=- -- *": [ "exec" ]
|
|
||||||
},
|
|
||||||
"ubus": {
|
"ubus": {
|
||||||
"luci.amneziawg": [
|
"luci.amneziawg": [
|
||||||
"getWgInstances"
|
"getAwgInstances"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"uci": [ "ddns", "system" ]
|
"uci": [ "ddns", "system", "network" ]
|
||||||
},
|
},
|
||||||
"write": {
|
"write": {
|
||||||
"ubus": {
|
"ubus": {
|
||||||
@@ -15,18 +15,33 @@ function command(cmd) {
|
|||||||
return trim(popen(cmd)?.read?.('all'));
|
return trim(popen(cmd)?.read?.('all'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkPeerHost(configHost, configPort, wgHost) {
|
||||||
|
const ips = popen(`resolveip ${shellquote(configHost)} 2>/dev/null`);
|
||||||
|
const hostIp = replace(wgHost, /\[|\]/g, "");
|
||||||
|
if (ips) {
|
||||||
|
for (let line = ips.read('line'); length(line); line = ips.read('line')) {
|
||||||
|
const ip = rtrim(line, '\n');
|
||||||
|
if (configPort && (ip + ":" + configPort == hostIp)) {
|
||||||
|
return true;
|
||||||
|
} else if (ip == substr(hostIp, 0, rindex(hostIp, ":"))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const methods = {
|
const methods = {
|
||||||
generatePsk: {
|
generatePsk: {
|
||||||
call: function() {
|
call: function() {
|
||||||
return { psk: command('amneziawg genpsk 2>/dev/null') };
|
return { psk: command('awg genpsk 2>/dev/null') };
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
generateKeyPair: {
|
generateKeyPair: {
|
||||||
call: function() {
|
call: function() {
|
||||||
const priv = command('amneziawg genkey 2>/dev/null');
|
const priv = command('awg genkey 2>/dev/null');
|
||||||
const pub = command(`echo ${shellquote(priv)} | amneziawg pubkey 2>/dev/null`);
|
const pub = command(`echo ${shellquote(priv)} | awg pubkey 2>/dev/null`);
|
||||||
|
|
||||||
return { keys: { priv, pub } };
|
return { keys: { priv, pub } };
|
||||||
}
|
}
|
||||||
@@ -36,20 +51,20 @@ const methods = {
|
|||||||
args: { privkey: "privkey" },
|
args: { privkey: "privkey" },
|
||||||
call: function(req) {
|
call: function(req) {
|
||||||
const priv = req.args?.privkey;
|
const priv = req.args?.privkey;
|
||||||
const pub = command(`echo ${shellquote(priv)} | amneziawg pubkey 2>/dev/null`);
|
const pub = command(`echo ${shellquote(priv)} | awg pubkey 2>/dev/null`);
|
||||||
|
|
||||||
return { keys: { priv, pub } };
|
return { keys: { priv, pub } };
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
getWgInstances: {
|
getAwgInstances: {
|
||||||
call: function() {
|
call: function() {
|
||||||
const data = {};
|
const data = {};
|
||||||
let last_device;
|
let last_device;
|
||||||
let qr_pubkey = {};
|
let qr_pubkey = {};
|
||||||
|
|
||||||
const uci = cursor();
|
const uci = cursor();
|
||||||
const wg_dump = popen("amneziawg show all dump 2>/dev/null");
|
const wg_dump = popen("awg show all dump 2>/dev/null");
|
||||||
|
|
||||||
if (wg_dump) {
|
if (wg_dump) {
|
||||||
uci.load("network");
|
uci.load("network");
|
||||||
@@ -74,12 +89,17 @@ const methods = {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
let peer_name;
|
let peer_name;
|
||||||
|
let peer_name_legacy;
|
||||||
|
|
||||||
uci.foreach('network', `amneziawg_${last_device}`, (s) => {
|
uci.foreach('network', `amneziawg_${last_device}`, (s) => {
|
||||||
if (s.public_key == record[1])
|
if (!s.disabled && s.public_key == record[1] && (!s.endpoint_host || checkPeerHost(s.endpoint_host, s.endpoint_port, record[3])))
|
||||||
peer_name = s.description;
|
peer_name = s.description;
|
||||||
|
if (s.public_key == record[1])
|
||||||
|
peer_name_legacy = s.description;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!peer_name) peer_name = peer_name_legacy;
|
||||||
|
|
||||||
const peer = {
|
const peer = {
|
||||||
name: peer_name,
|
name: peer_name,
|
||||||
public_key: record[1],
|
public_key: record[1],
|
||||||
Reference in New Issue
Block a user