mirror of
https://github.com/Slava-Shchipunov/awg-openwrt.git
synced 2026-03-20 11:55:48 +00:00
Compare commits
6 Commits
feat/add-i
...
v24.10.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c726cacbf | ||
|
|
d91b8929de | ||
|
|
33e363e9d9 | ||
|
|
3d865a8d4d | ||
|
|
e285146833 | ||
|
|
1dd92441aa |
@@ -7,8 +7,8 @@ on:
|
|||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- "SNAPSHOT"
|
- "SNAPSHOT"
|
||||||
schedule:
|
# schedule:
|
||||||
- cron: '0 */4 * * *'
|
# - cron: '0 */4 * * *'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|||||||
6
.github/workflows/run-release.yml
vendored
6
.github/workflows/run-release.yml
vendored
@@ -1,8 +1,8 @@
|
|||||||
name: Sync OpenWRT Releases
|
name: Sync OpenWRT Releases
|
||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
# schedule:
|
||||||
- cron: '0 0 */3 * *' # Проверка новых релизов раз в три дня
|
# - cron: '0 0 */3 * *' # Проверка новых релизов раз в три дня
|
||||||
workflow_dispatch: # Возможность вручную запустить Action
|
workflow_dispatch: # Возможность вручную запустить Action
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -63,4 +63,4 @@ jobs:
|
|||||||
if: needs.sync-releases.outputs.release_exists == 'false'
|
if: needs.sync-releases.outputs.release_exists == 'false'
|
||||||
uses: Slava-Shchipunov/awg-openwrt/.github/workflows/build-module.yml@master
|
uses: Slava-Shchipunov/awg-openwrt/.github/workflows/build-module.yml@master
|
||||||
with:
|
with:
|
||||||
tag_name: ${{ needs.sync-releases.outputs.release_tag }}
|
tag_name: ${{ needs.sync-releases.outputs.release_tag }}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
Если же вам нужно только установить пакеты, я добавил скрипт amneziawg-install - он автоматически скачает пакеты из этого репозитория под ваше устройство (только для стабильной версии OpenWRT), а также предложит сразу настроить интерфейс с протоколом AmneziaWG. Если пользователь согласится, нужно будет ввести параметры конфига, которые запросит скрипт. При этом скрипт создаст интерфейс, настроит для него правила фаерволла, а также **включит перенаправление всего траффика через тунель AmneziaWG** (установит в настройках Peer галочку Route Allowed IPs).
|
Если же вам нужно только установить пакеты, я добавил скрипт amneziawg-install - он автоматически скачает пакеты из этого репозитория под ваше устройство (только для стабильной версии OpenWRT), а также предложит сразу настроить интерфейс с протоколом AmneziaWG. Если пользователь согласится, нужно будет ввести параметры конфига, которые запросит скрипт. При этом скрипт создаст интерфейс, настроит для него правила фаерволла, а также **включит перенаправление всего траффика через тунель AmneziaWG** (установит в настройках Peer галочку Route Allowed IPs).
|
||||||
Для запуска скрипта подключитесь к роутеру по SSH, введите команду и следуйте инструкциям на экране:
|
Для запуска скрипта подключитесь к роутеру по SSH, введите команду и следуйте инструкциям на экране:
|
||||||
```
|
```
|
||||||
sh <(wget -O - https://raw.githubusercontent.com/Slava-Shchipunov/awg-openwrt/refs/heads/feat/add-install-script/amneziawg-install.sh)
|
sh <(wget -O - https://raw.githubusercontent.com/Slava-Shchipunov/awg-openwrt/refs/heads/master/amneziawg-install.sh)
|
||||||
```
|
```
|
||||||
|
|
||||||
# Сборка пакетов для всех устройств, поддерживающих OpenWRT
|
# Сборка пакетов для всех устройств, поддерживающих OpenWRT
|
||||||
@@ -51,7 +51,7 @@ For automatic configuration, I recommend using the [script](https://github.com/i
|
|||||||
If you only need to install packages, I added the amneziawg-install script - it will automatically download packages from this repository for your device (only for the stable version of OpenWRT), and also offer to immediately configure the interface with the AmneziaWG protocol. If the user agrees, you will need to enter the config parameters that the script will request. The script will create an interface, configure firewall rules for it, and also **enable redirection of all traffic through the AmneziaWG tunnel** (check the Route Allowed IPs box in the Peer settings).
|
If you only need to install packages, I added the amneziawg-install script - it will automatically download packages from this repository for your device (only for the stable version of OpenWRT), and also offer to immediately configure the interface with the AmneziaWG protocol. If the user agrees, you will need to enter the config parameters that the script will request. The script will create an interface, configure firewall rules for it, and also **enable redirection of all traffic through the AmneziaWG tunnel** (check the Route Allowed IPs box in the Peer settings).
|
||||||
To run the script, connect to the router via SSH, enter the command and follow the instructions on the screen:
|
To run the script, connect to the router via SSH, enter the command and follow the instructions on the screen:
|
||||||
```
|
```
|
||||||
sh <(wget -O - https://raw.githubusercontent.com/Slava-Shchipunov/awg-openwrt/refs/heads/feat/add-install-script/amneziawg-install.sh)
|
sh <(wget -O - https://raw.githubusercontent.com/Slava-Shchipunov/awg-openwrt/refs/heads/master/amneziawg-install.sh)
|
||||||
```
|
```
|
||||||
|
|
||||||
# Building packages for all devices that support OpenWRT
|
# Building packages for all devices that support OpenWRT
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
LUCI_TITLE:=Support for AmneziaWG VPN
|
LUCI_TITLE:=Support for AmneziaWG VPN
|
||||||
LUCI_DEPENDS:=+amneziawg-tools +ucode
|
LUCI_DEPENDS:=+amneziawg-tools +ucode +qrencode
|
||||||
LUCI_PKGARCH:=all
|
LUCI_PKGARCH:=all
|
||||||
|
|
||||||
PKG_PROVIDES:=luci-app-amneziawg
|
PKG_PROVIDES:=luci-app-amneziawg
|
||||||
|
|||||||
@@ -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', [
|
return fs.exec_direct('/usr/bin/qrencode', [
|
||||||
'--inline', '--8bit', '--type=SVG',
|
'--inline', '--8bit', '--type=SVG',
|
||||||
'--output=-', '--', data
|
'--output=-', '--', data
|
||||||
]).then(function(svg) {
|
]).then(function(svg) {
|
||||||
code.style.opacity = '';
|
div.style.opacity = '';
|
||||||
dom.content(code, Object.assign(E(svg), { style: 'width:100%;height:auto' }));
|
dom.content(code, Object.assign(E(svg), { style: 'width:100%;height:auto' }));
|
||||||
}).catch(function(error) {
|
}).catch(function(error) {
|
||||||
code.style.opacity = '';
|
div.style.opacity = '';
|
||||||
|
|
||||||
if (L.isObject(error) && error.name == 'NotFoundError') {
|
if (L.isObject(error) && error.name == 'NotFoundError') {
|
||||||
dom.content(code, [
|
dom.content(code, [
|
||||||
@@ -402,15 +416,15 @@ 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.awg_jc);
|
s.getOption('awg_jc').getUIElement(s.section).setValue(config.interface_jc);
|
||||||
s.getOption('awg_jmin').getUIElement(s.section).setValue(config.awg_jmin);
|
s.getOption('awg_jmin').getUIElement(s.section).setValue(config.interface_jmin);
|
||||||
s.getOption('awg_jmax').getUIElement(s.section).setValue(config.awg_jmax);
|
s.getOption('awg_jmax').getUIElement(s.section).setValue(config.interface_jmax);
|
||||||
s.getOption('awg_s1').getUIElement(s.section).setValue(config.awg_s1);
|
s.getOption('awg_s1').getUIElement(s.section).setValue(config.interface_s1);
|
||||||
s.getOption('awg_s2').getUIElement(s.section).setValue(config.awg_s2);
|
s.getOption('awg_s2').getUIElement(s.section).setValue(config.interface_s2);
|
||||||
s.getOption('awg_h1').getUIElement(s.section).setValue(config.awg_h1);
|
s.getOption('awg_h1').getUIElement(s.section).setValue(config.interface_h1);
|
||||||
s.getOption('awg_h2').getUIElement(s.section).setValue(config.awg_h2);
|
s.getOption('awg_h2').getUIElement(s.section).setValue(config.interface_h2);
|
||||||
s.getOption('awg_h3').getUIElement(s.section).setValue(config.awg_h3);
|
s.getOption('awg_h3').getUIElement(s.section).setValue(config.interface_h3);
|
||||||
s.getOption('awg_h4').getUIElement(s.section).setValue(config.awg_h4);
|
s.getOption('awg_h4').getUIElement(s.section).setValue(config.interface_h4);
|
||||||
|
|
||||||
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);
|
||||||
@@ -743,39 +757,65 @@ return network.registerProtocol('amneziawg', {
|
|||||||
|
|
||||||
o.modalonly = true;
|
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'),
|
var pub = s.formvalue(s.section, 'public_key'),
|
||||||
port = s.formvalue(s.section, 'listen_port') || '51820',
|
port = s.formvalue(s.section, 'listen_port') || '51820',
|
||||||
jc = s.formvalue
|
prv = this.section.formvalue(section_id, 'private_key'),
|
||||||
prv = this.section.formvalue(section_id, 'private_key'),
|
psk = this.section.formvalue(section_id, 'preshared_key'),
|
||||||
psk = this.section.formvalue(section_id, 'preshared_key'),
|
eport = this.section.formvalue(section_id, 'endpoint_port'),
|
||||||
eport = this.section.formvalue(section_id, 'endpoint_port'),
|
keep = this.section.formvalue(section_id, 'persistent_keepalive'),
|
||||||
keep = this.section.formvalue(section_id, 'persistent_keepalive');
|
jc = s.formvalue(s.section, 'awg_jc'),
|
||||||
|
jmin = s.formvalue(s.section, 'awg_jmin'),
|
||||||
// If endpoint is IPv6 we must escape it with []
|
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) {
|
if (endpoint.indexOf(':') > 0) {
|
||||||
endpoint = '['+endpoint+']';
|
endpoint = '[' + endpoint + ']';
|
||||||
}
|
}
|
||||||
|
var configLines = [
|
||||||
return [
|
|
||||||
'[Interface]',
|
'[Interface]',
|
||||||
'PrivateKey = ' + prv,
|
'PrivateKey = ' + prv,
|
||||||
eport ? 'ListenPort = ' + eport : '# ListenPort not defined',
|
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]',
|
'[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');
|
||||||
|
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
network.getWANNetworks(),
|
network.getWANNetworks(),
|
||||||
@@ -804,21 +844,33 @@ return network.registerProtocol('amneziawg', {
|
|||||||
|
|
||||||
var ips = [ '0.0.0.0/0', '::/0' ];
|
var ips = [ '0.0.0.0/0', '::/0' ];
|
||||||
|
|
||||||
|
var dns = [];
|
||||||
|
|
||||||
var qrm, qrs, qro;
|
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;
|
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');
|
||||||
|
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());
|
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);
|
invokeQREncode(conf.firstChild.data, code);
|
||||||
@@ -836,18 +888,36 @@ return network.registerProtocol('amneziawg', {
|
|||||||
ips.forEach(function(ip) { qro.value(ip) });
|
ips.forEach(function(ip) { qro.value(ip) });
|
||||||
qro.onchange = handleConfigChange;
|
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 = qrs.option(form.DummyValue, 'output');
|
||||||
qro.renderWidget = function() {
|
qro.renderWidget = function() {
|
||||||
var peer_config = configGenerator(hostnames[0], ips);
|
var peer_config = configGenerator(hostnames[0], ips, eips, dns);
|
||||||
|
|
||||||
var node = E('div', {
|
var node = E('div', {
|
||||||
'style': 'display:flex;flex-wrap:wrap;align-items:center;gap:.5em;width:100%'
|
'style': 'display:flex;flex-wrap:wrap;align-items:center;gap:.5em;width:100%'
|
||||||
}, [
|
}, [
|
||||||
E('div', {
|
E('div', {
|
||||||
'class': 'qr-code',
|
'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', {
|
E('pre', {
|
||||||
'class': 'client-config',
|
'class': 'client-config',
|
||||||
|
|||||||
Reference in New Issue
Block a user