4 Commits

Author SHA1 Message Date
RTechSn
0c726cacbf Fix Generate Configuration (#36)
* Fix "generate client configuration"

* Add qrencode dependency

* Added client IP and DNS settings in client config generator

* Added Download Config button

* fix
2025-06-26 01:34:20 +07:00
EugeneTM
d91b8929de fix var names in config import (#35)
Исправлены названия переменных для корректного импорта текстовой конфигурации
2025-03-27 21:21:14 +07:00
Slava-Shchipunov
33e363e9d9 feat: disable sync owrt releases 2025-03-13 09:24:17 +07:00
Slava-Shchipunov
3d865a8d4d feat: disable build to snapshots 2025-03-13 09:22:29 +07:00
4 changed files with 114 additions and 44 deletions

View File

@@ -7,8 +7,8 @@ on:
push:
tags:
- "SNAPSHOT"
schedule:
- cron: '0 */4 * * *'
# schedule:
# - cron: '0 */4 * * *'
workflow_dispatch:
jobs:

View File

@@ -1,8 +1,8 @@
name: Sync OpenWRT Releases
on:
schedule:
- cron: '0 0 */3 * *' # Проверка новых релизов раз в три дня
# schedule:
# - cron: '0 0 */3 * *' # Проверка новых релизов раз в три дня
workflow_dispatch: # Возможность вручную запустить Action
jobs:
@@ -63,4 +63,4 @@ jobs:
if: needs.sync-releases.outputs.release_exists == 'false'
uses: Slava-Shchipunov/awg-openwrt/.github/workflows/build-module.yml@master
with:
tag_name: ${{ needs.sync-releases.outputs.release_tag }}
tag_name: ${{ needs.sync-releases.outputs.release_tag }}

View File

@@ -7,7 +7,7 @@
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Support for AmneziaWG VPN
LUCI_DEPENDS:=+amneziawg-tools +ucode
LUCI_DEPENDS:=+amneziawg-tools +ucode +qrencode
LUCI_PKGARCH:=all
PKG_PROVIDES:=luci-app-amneziawg

View File

@@ -64,15 +64,29 @@ function generateDescription(name, texts) {
]);
}
function invokeQREncode(data, code) {
function invokeQREncode(data, div) {
var code = div.children[0];
var btn = div.children[1];
dom.content(btn, [
E('a', {
'class': 'btn cbi-button-action',
'style': 'text-align: center',
'href': 'data:text/plain;charset=utf-8,' + encodeURIComponent(data),
'download': 'amneziawg.conf'
}, ['Download Configuration']),
]);
return fs.exec_direct('/usr/bin/qrencode', [
'--inline', '--8bit', '--type=SVG',
'--output=-', '--', data
]).then(function(svg) {
code.style.opacity = '';
div.style.opacity = '';
dom.content(code, Object.assign(E(svg), { style: 'width:100%;height:auto' }));
}).catch(function(error) {
code.style.opacity = '';
div.style.opacity = '';
if (L.isObject(error) && error.name == 'NotFoundError') {
dom.content(code, [
@@ -402,15 +416,15 @@ return network.registerProtocol('amneziawg', {
s.getOption('public_key').getUIElement(s.section).setValue(keypair.pub);
s.getOption('listen_port').getUIElement(s.section).setValue(config.interface_listenport || '');
s.getOption('addresses').getUIElement(s.section).setValue(config.interface_address);
s.getOption('awg_jc').getUIElement(s.section).setValue(config.awg_jc);
s.getOption('awg_jmin').getUIElement(s.section).setValue(config.awg_jmin);
s.getOption('awg_jmax').getUIElement(s.section).setValue(config.awg_jmax);
s.getOption('awg_s1').getUIElement(s.section).setValue(config.awg_s1);
s.getOption('awg_s2').getUIElement(s.section).setValue(config.awg_s2);
s.getOption('awg_h1').getUIElement(s.section).setValue(config.awg_h1);
s.getOption('awg_h2').getUIElement(s.section).setValue(config.awg_h2);
s.getOption('awg_h3').getUIElement(s.section).setValue(config.awg_h3);
s.getOption('awg_h4').getUIElement(s.section).setValue(config.awg_h4);
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_jmax').getUIElement(s.section).setValue(config.interface_jmax);
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_h1').getUIElement(s.section).setValue(config.interface_h1);
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);
if (config.interface_dns)
s.getOption('dns').getUIElement(s.section).setValue(config.interface_dns);
@@ -743,39 +757,65 @@ return network.registerProtocol('amneziawg', {
o.modalonly = true;
o.createPeerConfig = function(section_id, endpoint, ips) {
o.createPeerConfig = function (section_id, endpoint, ips, eips, dns) {
var pub = s.formvalue(s.section, 'public_key'),
port = s.formvalue(s.section, 'listen_port') || '51820',
jc = s.formvalue
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 []
port = s.formvalue(s.section, 'listen_port') || '51820',
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'),
jc = s.formvalue(s.section, 'awg_jc'),
jmin = s.formvalue(s.section, 'awg_jmin'),
jmax = s.formvalue(s.section, 'awg_jmax'),
s1 = s.formvalue(s.section, 'awg_s1'),
s2 = s.formvalue(s.section, 'awg_s2'),
h1 = s.formvalue(s.section, 'awg_h1'),
h2 = s.formvalue(s.section, 'awg_h2'),
h3 = s.formvalue(s.section, 'awg_h3'),
h4 = s.formvalue(s.section, 'awg_h4');
if (endpoint.indexOf(':') > 0) {
endpoint = '['+endpoint+']';
endpoint = '[' + endpoint + ']';
}
return [
var configLines = [
'[Interface]',
'PrivateKey = ' + prv,
eport ? 'ListenPort = ' + eport : '# ListenPort not defined',
eips && eips.length ? 'Address = ' + eips.join(', ') : '# Address not defined',
dns && dns.length ? 'DNS = ' + dns.join(', ') : '# DNS not defined',
''
];
if (jc) configLines.push('jc = ' + jc);
if (jmin) configLines.push('jmin = ' + jmin);
if (jmax) configLines.push('jmax = ' + jmax);
if (s1) configLines.push('s1 = ' + s1);
if (s2) configLines.push('s2 = ' + s2);
if (h1) configLines.push('h1 = ' + h1);
if (h2) configLines.push('h2 = ' + h2);
if (h3) configLines.push('h3 = ' + h3);
if (h4) configLines.push('h4 = ' + h4);
configLines.push(
'',
'[Peer]',
'PublicKey = ' + pub,
psk ? 'PresharedKey = ' + psk : '# PresharedKey not used',
ips && ips.length ? 'AllowedIPs = ' + ips.join(', ') : '# AllowedIPs not defined',
endpoint ? 'Endpoint = ' + endpoint + ':' + port : '# Endpoint not defined',
keep ? 'PersistentKeepAlive = ' + keep : '# PersistentKeepAlive not defined'
].join('\n');
};
keep ? 'PersistentKeepAlive = ' + keep : '# PersistentKeepAlive not defined',
''
);
return configLines.join('\n');
};
o.handleGenerateQR = function(section_id, ev) {
var mapNode = ss.getActiveModalMap(),
headNode = mapNode.parentNode.querySelector('h4'),
configGenerator = this.createPeerConfig.bind(this, section_id),
parent = this.map;
headNode = mapNode.parentNode.querySelector('h4'),
configGenerator = this.createPeerConfig.bind(this, section_id),
parent = this.map,
eips = this.section.formvalue(section_id, 'allowed_ips');
return Promise.all([
network.getWANNetworks(),
@@ -804,21 +844,33 @@ return network.registerProtocol('amneziawg', {
var ips = [ '0.0.0.0/0', '::/0' ];
var dns = [];
var qrm, qrs, qro;
qrm = new form.JSONMap({ config: { endpoint: hostnames[0], allowed_ips: ips } }, null, _('The generated configuration can be imported into a AmneziaWG client application to set up a connection towards this device.'));
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 AmneziaWG client application to set up a connection towards this device.'));
qrm.parent = parent;
qrs = qrm.section(form.NamedSection, 'config');
function handleConfigChange(ev, section_id, value) {
var code = this.map.findElement('.qr-code'),
conf = this.map.findElement('.client-config'),
endpoint = this.section.getUIElement(section_id, 'endpoint'),
ips = this.section.getUIElement(section_id, 'allowed_ips');
conf = this.map.findElement('.client-config'),
endpoint = this.section.getUIElement(section_id, 'endpoint'),
ips = this.section.getUIElement(section_id, 'allowed_ips');
eips = this.section.getUIElement(section_id, 'addresses');
dns = this.section.getUIElement(section_id, 'dns_servers');
if (this.isValid(section_id)) {
conf.firstChild.data = configGenerator(endpoint.getValue(), ips.getValue());
conf.firstChild.data = configGenerator(endpoint.getValue(), ips.getValue(), eips.getValue(), dns.getValue());
code.style.opacity = '.5';
invokeQREncode(conf.firstChild.data, code);
@@ -836,18 +888,36 @@ return network.registerProtocol('amneziawg', {
ips.forEach(function(ip) { qro.value(ip) });
qro.onchange = handleConfigChange;
qro = qrs.option(form.DynamicList, 'dns_servers', _('DNS Servers'), _('DNS servers for the remote clients using this tunnel to your openwrt device. Some wireguard clients require this to be set.'));
qro.datatype = 'ipaddr';
qro.default = dns;
qro.onchange = handleConfigChange;
qro = qrs.option(form.DynamicList, 'addresses', _('Addresses'), _('IP addresses for the peer to use inside the tunnel. Some clients require this setting.'));
qro.datatype = 'ipaddr';
qro.default = eips;
eips.forEach(function(eip) { qro.value(eip) });
qro.onchange = handleConfigChange;
qro = qrs.option(form.DummyValue, 'output');
qro.renderWidget = function() {
var peer_config = configGenerator(hostnames[0], ips);
var peer_config = configGenerator(hostnames[0], ips, eips, dns);
var node = E('div', {
'style': 'display:flex;flex-wrap:wrap;align-items:center;gap:.5em;width:100%'
}, [
E('div', {
'class': 'qr-code',
'style': 'width:320px;flex:0 1 320px;text-align:center'
'style': 'display:flex; flex-direction: column; text-align: center',
}, [
E('em', { 'class': 'spinning' }, [ _('Generating QR code…') ])
E('div', {
'style': 'width:320px;flex:0 1 320px;text-align:center'
}, [
E('em', { 'class': 'spinning' }, [ _('Generating QR code…') ])
]),
E('div', {
}, ['Download Configuration']),
]),
E('pre', {
'class': 'client-config',