update 2025-02-05 00:40:51
This commit is contained in:
parent
0fd7b11ec8
commit
1a88d24929
17
luci-app-openvpn-server/Makefile
Normal file
17
luci-app-openvpn-server/Makefile
Normal file
@ -0,0 +1,17 @@
|
||||
# Copyright (C) 2016 Openwrt.org
|
||||
#
|
||||
# This is free software, licensed under the Apache License, Version 2.0 .
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_TITLE:=LuCI support for OpenVPN Server
|
||||
LUCI_DEPENDS:=+openvpn-openssl +openvpn-easy-rsa +kmod-tun
|
||||
LUCI_PKGARCH:=all
|
||||
PKG_NAME:=luci-app-openvpn-server
|
||||
PKG_VERSION:=3.0
|
||||
PKG_RELEASE:=0
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
# call BuildPackage - OpenWrt buildroot signature
|
24
luci-app-openvpn-server/luasrc/controller/openvpn-server.lua
Normal file
24
luci-app-openvpn-server/luasrc/controller/openvpn-server.lua
Normal file
@ -0,0 +1,24 @@
|
||||
|
||||
module("luci.controller.openvpn-server", package.seeall)
|
||||
|
||||
function index()
|
||||
if not nixio.fs.access("/etc/config/openvpn") then
|
||||
return
|
||||
end
|
||||
|
||||
entry({"admin", "vpn"}, firstchild(), "VPN", 45).dependent = false
|
||||
|
||||
local page
|
||||
|
||||
page = entry({"admin", "vpn", "openvpn-server"}, cbi("openvpn-server/openvpn-server"), _("OpenVPN Server"), 80)
|
||||
page.dependent = false
|
||||
page.acl_depends = { "luci-app-openvpn-server" }
|
||||
entry({"admin", "vpn", "openvpn-server","status"},call("act_status")).leaf=true
|
||||
end
|
||||
|
||||
function act_status()
|
||||
local e={}
|
||||
e.running=luci.sys.call("pgrep openvpn >/dev/null")==0
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(e)
|
||||
end
|
@ -0,0 +1,108 @@
|
||||
|
||||
--require("luci.tools.webadmin")
|
||||
|
||||
mp = Map("openvpn", translate("OpenVPN Server"), translate("An easy config OpenVPN Server Web-UI"))
|
||||
|
||||
mp:section(SimpleSection).template = "openvpn/openvpn_status"
|
||||
|
||||
s = mp:section(TypedSection, "openvpn")
|
||||
s.anonymous = true
|
||||
s.addremove = false
|
||||
|
||||
s:tab("basic", translate("Base Setting"))
|
||||
|
||||
o = s:taboption("basic", Flag, "enabled", translate("Enable"))
|
||||
|
||||
proto = s:taboption("basic", Value, "proto", translate("Proto"))
|
||||
proto:value("tcp4", translate("TCP Server IPv4"))
|
||||
proto:value("udp4", translate("UDP Server IPv4"))
|
||||
proto:value("tcp6", translate("TCP Server IPv6"))
|
||||
proto:value("udp6", translate("UDP Server IPv6"))
|
||||
|
||||
port = s:taboption("basic", Value, "port", translate("Port"))
|
||||
port.datatype = "range(1, 65535)"
|
||||
|
||||
ddns = s:taboption("basic", Value, "ddns", translate("WAN DDNS or IP"))
|
||||
ddns.datatype = "string"
|
||||
ddns.default = "exmple.com"
|
||||
ddns.rmempty = false
|
||||
|
||||
localnet = s:taboption("basic", Value, "server", translate("Client Network"))
|
||||
localnet.datatype = "string"
|
||||
localnet.description = translate("VPN Client Network IP with subnet")
|
||||
|
||||
list = s:taboption("basic", DynamicList, "push")
|
||||
list.title = translate("Client Settings")
|
||||
list.datatype = "string"
|
||||
list.description = translate("Set route 192.168.0.0 255.255.255.0 and dhcp-option DNS 192.168.0.1 base on your router")
|
||||
|
||||
local o
|
||||
o = s:taboption("basic", Button, "certificate", translate("OpenVPN Client config file"))
|
||||
o.inputtitle = translate("Download .ovpn file")
|
||||
o.description = translate("If you are using IOS client, please download this .ovpn file and send it via QQ or Email to your IOS device")
|
||||
o.inputstyle = "reload"
|
||||
o.write = function()
|
||||
luci.sys.call("sh /etc/openvpn/genovpn.sh 2>&1 >/dev/null")
|
||||
Download()
|
||||
end
|
||||
|
||||
local o
|
||||
o = s:taboption("basic", Button, "renew_certificate", translate("Renew OpenVPN certificate files"))
|
||||
o.inputtitle = translate("Renew")
|
||||
o.inputstyle = "reload"
|
||||
o.write = function()
|
||||
luci.sys.call("sh /etc/openvpn/renewcert.sh 2>&1 >/dev/null &")
|
||||
end
|
||||
|
||||
s:tab("code", translate("Special Code"))
|
||||
|
||||
local conf = "/etc/openvpn-addon.conf"
|
||||
local NXFS = require "nixio.fs"
|
||||
o = s:taboption("code", TextValue, "conf")
|
||||
o.description = translate("(!)Special Code you know that add in to client .ovpn file")
|
||||
o.rows = 13
|
||||
o.wrap = "off"
|
||||
o.cfgvalue = function(self, section)
|
||||
return NXFS.readfile(conf) or ""
|
||||
end
|
||||
o.write = function(self, section, value)
|
||||
NXFS.writefile(conf, value:gsub("\r\n", "\n"))
|
||||
end
|
||||
|
||||
local pid = luci.util.exec("/usr/bin/pgrep openvpn")
|
||||
|
||||
function openvpn_process_status()
|
||||
local status = "OpenVPN is not running now "
|
||||
|
||||
if pid ~= "" then
|
||||
status = "OpenVPN is running with the PID " .. pid .. ""
|
||||
end
|
||||
|
||||
local status = { status=status }
|
||||
local table = { pid=status }
|
||||
return table
|
||||
end
|
||||
|
||||
function Download()
|
||||
local t,e
|
||||
t=nixio.open("/tmp/my.ovpn","r")
|
||||
luci.http.header('Content-Disposition','attachment; filename="my.ovpn"')
|
||||
luci.http.prepare_content("application/octet-stream")
|
||||
while true do
|
||||
e=t:read(nixio.const.buffersize)
|
||||
if(not e)or(#e==0)then
|
||||
break
|
||||
else
|
||||
luci.http.write(e)
|
||||
end
|
||||
end
|
||||
t:close()
|
||||
luci.http.close()
|
||||
end
|
||||
|
||||
function mp.on_after_commit(self)
|
||||
os.execute("uci set firewall.openvpn.dest_port=$(uci get openvpn.myvpn.port) && uci commit firewall && /etc/init.d/firewall restart")
|
||||
os.execute("/etc/init.d/openvpn restart")
|
||||
end
|
||||
|
||||
return mp
|
@ -0,0 +1,22 @@
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
XHR.poll(3, '<%=url([[admin]], [[vpn]], [[openvpn-server]], [[status]])%>', null,
|
||||
function(x, data) {
|
||||
var tb = document.getElementById('openvpn_status');
|
||||
if (data && tb) {
|
||||
if (data.running) {
|
||||
var links = '<em><b><font color=green><%=pcdata(translate("OpenVPN Server"))%> <%:RUNNING%></font></b></em>';
|
||||
tb.innerHTML = links;
|
||||
} else {
|
||||
tb.innerHTML = '<em><b><font color=red><%=pcdata(translate("OpenVPN Server"))%> <%:NOT RUNNING%></font></b></em>';
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
//]]>
|
||||
</script>
|
||||
<style>.mar-10 {margin-left: 50px; margin-right: 10px;}</style>
|
||||
<fieldset class="cbi-section">
|
||||
<p id="openvpn_status">
|
||||
<em><%:Collecting data...%></em>
|
||||
</p>
|
||||
</fieldset>
|
1
luci-app-openvpn-server/po/zh-cn
Symbolic link
1
luci-app-openvpn-server/po/zh-cn
Symbolic link
@ -0,0 +1 @@
|
||||
zh_Hans
|
104
luci-app-openvpn-server/po/zh_Hans/openvpn-server.po
Normal file
104
luci-app-openvpn-server/po/zh_Hans/openvpn-server.po
Normal file
@ -0,0 +1,104 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: zh_Hans\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: applications/luci-app-openvpn-server/luasrc/controller/openvpn-server.lua:13
|
||||
#: applications/luci-app-openvpn-server/luasrc/model/cbi/openvpn-server/openvpn-server.lua:4
|
||||
#: applications/luci-app-openvpn-server/luasrc/view/openvpn/openvpn_status.htm:7
|
||||
#: applications/luci-app-openvpn-server/luasrc/view/openvpn/openvpn_status.htm:10
|
||||
msgid "OpenVPN Server"
|
||||
msgstr "OpenVPN 服务器"
|
||||
|
||||
#: applications/luci-app-openvpn-server/luasrc/model/cbi/openvpn-server/openvpn-server.lua:4
|
||||
msgid "An easy config OpenVPN Server Web-UI"
|
||||
msgstr "易于使用的 OpenVPN 服务器 Web-UI"
|
||||
|
||||
#: applications/luci-app-openvpn-server/luasrc/model/cbi/openvpn-server/openvpn-server.lua:12
|
||||
msgid "Base Setting"
|
||||
msgstr "基本设置"
|
||||
|
||||
#: applications/luci-app-openvpn-server/luasrc/model/cbi/openvpn-server/openvpn-server.lua:14
|
||||
msgid "Enable"
|
||||
msgstr "启用"
|
||||
|
||||
#: applications/luci-app-openvpn-server/luasrc/model/cbi/openvpn-server/openvpn-server.lua:16
|
||||
msgid "Proto"
|
||||
msgstr "协议"
|
||||
|
||||
#: applications/luci-app-openvpn-server/luasrc/model/cbi/openvpn-server/openvpn-server.lua:17
|
||||
msgid "TCP Server IPv4"
|
||||
msgstr "TCP Server IPv4"
|
||||
|
||||
#: applications/luci-app-openvpn-server/luasrc/model/cbi/openvpn-server/openvpn-server.lua:18
|
||||
msgid "UDP Server IPv4"
|
||||
msgstr "UDP Server IPv4"
|
||||
|
||||
#: applications/luci-app-openvpn-server/luasrc/model/cbi/openvpn-server/openvpn-server.lua:19
|
||||
msgid "TCP Server IPv6"
|
||||
msgstr "TCP Server IPv6"
|
||||
|
||||
#: applications/luci-app-openvpn-server/luasrc/model/cbi/openvpn-server/openvpn-server.lua:20
|
||||
msgid "UDP Server IPv6"
|
||||
msgstr "UDP Server IPv6"
|
||||
|
||||
#: applications/luci-app-openvpn-server/luasrc/model/cbi/openvpn-server/openvpn-server.lua:22
|
||||
msgid "Port"
|
||||
msgstr "端口"
|
||||
|
||||
#: applications/luci-app-openvpn-server/luasrc/model/cbi/openvpn-server/openvpn-server.lua:25
|
||||
msgid "WAN DDNS or IP"
|
||||
msgstr "WAN口的 DDNS域名 或者 IP"
|
||||
|
||||
#: applications/luci-app-openvpn-server/luasrc/model/cbi/openvpn-server/openvpn-server.lua:30
|
||||
msgid "Client Network"
|
||||
msgstr "客户端网段"
|
||||
|
||||
#: applications/luci-app-openvpn-server/luasrc/model/cbi/openvpn-server/openvpn-server.lua:32
|
||||
msgid "VPN Client Network IP with subnet"
|
||||
msgstr "客户端分配的网段地址(默认为 10.8.0.0 255.255.255.0)"
|
||||
|
||||
#: applications/luci-app-openvpn-server/luasrc/model/cbi/openvpn-server/openvpn-server.lua:35
|
||||
msgid "Client Settings"
|
||||
msgstr "客户端推送配置"
|
||||
|
||||
#: applications/luci-app-openvpn-server/luasrc/model/cbi/openvpn-server/openvpn-server.lua:37
|
||||
msgid ""
|
||||
"Set route 192.168.0.0 255.255.255.0 and dhcp-option DNS 192.168.0.1 base on "
|
||||
"your router"
|
||||
msgstr "根据路由的实际LAN IP 修改 route 192.168.0.0 255.255.255.0 和 dhcp-option DNS 192.168.0.1 这两行"
|
||||
|
||||
#: applications/luci-app-openvpn-server/luasrc/model/cbi/openvpn-server/openvpn-server.lua:41
|
||||
msgid "OpenVPN Client config file"
|
||||
msgstr "OpenVPN 客户端配置文件"
|
||||
|
||||
#: applications/luci-app-openvpn-server/luasrc/model/cbi/openvpn-server/openvpn-server.lua:42
|
||||
msgid "Download .ovpn file"
|
||||
msgstr "一键下载 .ovpn 文件"
|
||||
|
||||
#: applications/luci-app-openvpn-server/luasrc/model/cbi/openvpn-server/openvpn-server.lua:43
|
||||
msgid ""
|
||||
"If you are using IOS client, please download this .ovpn file and send it via "
|
||||
"QQ or Email to your IOS device"
|
||||
msgstr "如果你使用的是 iOS 设备,你可以使用 QQ 或者邮件发送到自己的设备上用 OpenVPN 客户端打开导入"
|
||||
|
||||
#: applications/luci-app-openvpn-server/luasrc/model/cbi/openvpn-server/openvpn-server.lua:51
|
||||
msgid "Renew OpenVPN certificate files"
|
||||
msgstr "重新生成 OpenVPN 证书文件"
|
||||
|
||||
#: applications/luci-app-openvpn-server/luasrc/model/cbi/openvpn-server/openvpn-server.lua:52
|
||||
msgid "Renew"
|
||||
msgstr "重新生成"
|
||||
|
||||
#: applications/luci-app-openvpn-server/luasrc/model/cbi/openvpn-server/openvpn-server.lua:58
|
||||
msgid "Special Code"
|
||||
msgstr "特殊代码"
|
||||
|
||||
#: applications/luci-app-openvpn-server/luasrc/model/cbi/openvpn-server/openvpn-server.lua:63
|
||||
msgid "(!)Special Code you know that add in to client .ovpn file"
|
||||
msgstr "(!)特殊代码将自动合并到客户端的 .ovpn 配置文件中"
|
27
luci-app-openvpn-server/root/etc/config/openvpn
Normal file
27
luci-app-openvpn-server/root/etc/config/openvpn
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
config openvpn 'myvpn'
|
||||
option enabled '0'
|
||||
option proto 'tcp-server'
|
||||
option port '1194'
|
||||
option ddns example.com
|
||||
option dev 'tun'
|
||||
option topology 'subnet'
|
||||
option server '10.8.0.0 255.255.255.0'
|
||||
option comp_lzo 'adaptive'
|
||||
option ca '/etc/openvpn/pki/ca.crt'
|
||||
option dh '/etc/openvpn/pki/dh.pem'
|
||||
option cert '/etc/openvpn/pki/server.crt'
|
||||
option key '/etc/openvpn/pki/server.key'
|
||||
option persist_key '1'
|
||||
option persist_tun '1'
|
||||
option user 'nobody'
|
||||
option group 'nogroup'
|
||||
option max_clients '10'
|
||||
option keepalive '10 120'
|
||||
option verb '3'
|
||||
option status '/var/log/openvpn_status.log'
|
||||
option log '/tmp/openvpn.log'
|
||||
list push 'route 192.168.1.0 255.255.255.0'
|
||||
list push 'comp-lzo adaptive'
|
||||
list push 'redirect-gateway def1 bypass-dhcp'
|
||||
list push 'dhcp-option DNS 192.168.1.1'
|
22
luci-app-openvpn-server/root/etc/easy-rsa/vars
Normal file
22
luci-app-openvpn-server/root/etc/easy-rsa/vars
Normal file
@ -0,0 +1,22 @@
|
||||
# A little housekeeping: DO NOT EDIT THIS SECTION
|
||||
#
|
||||
# Easy-RSA 3.x does not source into the environment directly.
|
||||
# Complain if a user tries to do this:
|
||||
if [ -z "$EASYRSA_CALLER" ]; then
|
||||
echo "You appear to be sourcing an Easy-RSA *vars* file. This is" >&2
|
||||
echo "no longer necessary and is disallowed. See the section called" >&2
|
||||
echo "*How to use this file* near the top comments for more details." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
set_var EASYRSA_KEY_SIZE 2048
|
||||
set_var EASYRSA_ALGO rsa
|
||||
set_var EASYRSA_CA_EXPIRE 3650
|
||||
set_var EASYRSA_CERT_EXPIRE 3650
|
||||
set_var EASYRSA_DN "org"
|
||||
set_var EASYRSA_REQ_COUNTRY "US"
|
||||
set_var EASYRSA_REQ_PROVINCE "California"
|
||||
set_var EASYRSA_REQ_CITY "San Francisco"
|
||||
set_var EASYRSA_REQ_ORG "OpenVPN"
|
||||
set_var EASYRSA_REQ_EMAIL "openvpn@openvpn.net"
|
||||
set_var EASYRSA_REQ_OU "OpenVPN"
|
1
luci-app-openvpn-server/root/etc/openvpn-addon.conf
Normal file
1
luci-app-openvpn-server/root/etc/openvpn-addon.conf
Normal file
@ -0,0 +1 @@
|
||||
comp-lzo
|
27
luci-app-openvpn-server/root/etc/openvpn/genovpn.sh
Executable file
27
luci-app-openvpn-server/root/etc/openvpn/genovpn.sh
Executable file
@ -0,0 +1,27 @@
|
||||
#!/bin/sh
|
||||
|
||||
ddns=`uci get openvpn.myvpn.ddns`
|
||||
port=`uci get openvpn.myvpn.port`
|
||||
proto=`uci get openvpn.myvpn.proto|sed -e 's/server/client/g'`
|
||||
|
||||
cat > /tmp/my.ovpn <<EOF
|
||||
client
|
||||
dev tun
|
||||
proto $proto
|
||||
remote $ddns $port
|
||||
resolv-retry infinite
|
||||
nobind
|
||||
persist-key
|
||||
persist-tun
|
||||
verb 3
|
||||
EOF
|
||||
echo '<ca>' >> /tmp/my.ovpn
|
||||
cat /etc/openvpn/pki/ca.crt >> /tmp/my.ovpn
|
||||
echo '</ca>' >> /tmp/my.ovpn
|
||||
echo '<cert>' >> /tmp/my.ovpn
|
||||
cat /etc/openvpn/pki/client1.crt >> /tmp/my.ovpn
|
||||
echo '</cert>' >> /tmp/my.ovpn
|
||||
echo '<key>' >> /tmp/my.ovpn
|
||||
cat /etc/openvpn/pki/client1.key >> /tmp/my.ovpn
|
||||
echo '</key>' >> /tmp/my.ovpn
|
||||
[ -f /etc/openvpn-addon.conf ] && cat /etc/openvpn-addon.conf >> /tmp/my.ovpn
|
34
luci-app-openvpn-server/root/etc/openvpn/renewcert.sh
Executable file
34
luci-app-openvpn-server/root/etc/openvpn/renewcert.sh
Executable file
@ -0,0 +1,34 @@
|
||||
#!/bin/sh
|
||||
|
||||
export EASYRSA_PKI="/etc/easy-rsa/pki"
|
||||
export EASYRSA_VARS_FILE="/etc/easy-rsa/vars"
|
||||
export EASYRSA_CLI="easyrsa --batch"
|
||||
|
||||
# Cleanup
|
||||
echo -en "yes\nyes\n" | $EASYRSA_CLI init-pki
|
||||
|
||||
# Generate DH
|
||||
$EASYRSA_CLI gen-dh
|
||||
|
||||
# Generate for the CA
|
||||
$EASYRSA_CLI build-ca nopass
|
||||
|
||||
# Generate for the server
|
||||
$EASYRSA_CLI build-server-full server nopass
|
||||
|
||||
# Generate for the client
|
||||
$EASYRSA_CLI build-client-full client1 nopass
|
||||
|
||||
# Copy files
|
||||
mkdir -p /etc/openvpn/pki
|
||||
cp /etc/easy-rsa/pki/ca.crt /etc/openvpn/pki/
|
||||
cp /etc/easy-rsa/pki/dh.pem /etc/openvpn/pki/
|
||||
cp /etc/easy-rsa/pki/issued/server.crt /etc/openvpn/pki/
|
||||
cp /etc/easy-rsa/pki/private/server.key /etc/openvpn/pki/
|
||||
cp /etc/easy-rsa/pki/issued/client1.crt /etc/openvpn/pki/
|
||||
cp /etc/easy-rsa/pki/private/client1.key /etc/openvpn/pki/
|
||||
|
||||
# Restart openvpn
|
||||
/etc/init.d/openvpn restart
|
||||
|
||||
echo "OpenVPN Cert renew successfully"
|
54
luci-app-openvpn-server/root/etc/uci-defaults/openvpn
Normal file
54
luci-app-openvpn-server/root/etc/uci-defaults/openvpn
Normal file
@ -0,0 +1,54 @@
|
||||
#!/bin/sh
|
||||
|
||||
openvpn_port="$(uci -q get openvpn.myvpn.port)"
|
||||
[ -z "$openvpn_port" ] && openvpn_port=1194
|
||||
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
delete network.vpn0
|
||||
set network.vpn0=interface
|
||||
set network.vpn0.ifname='tun0'
|
||||
set network.vpn0.proto='none'
|
||||
|
||||
commit network
|
||||
|
||||
delete firewall.openvpn
|
||||
set firewall.openvpn=rule
|
||||
set firewall.openvpn.name='openvpn'
|
||||
set firewall.openvpn.target='ACCEPT'
|
||||
set firewall.openvpn.src='wan'
|
||||
set firewall.openvpn.proto='tcp udp'
|
||||
set firewall.openvpn.dest_port="$openvpn_port"
|
||||
|
||||
delete firewall.vpn
|
||||
set firewall.vpn=zone
|
||||
set firewall.vpn.name='vpn'
|
||||
set firewall.vpn.input='ACCEPT'
|
||||
set firewall.vpn.forward='ACCEPT'
|
||||
set firewall.vpn.output='ACCEPT'
|
||||
set firewall.vpn.masq='1'
|
||||
set firewall.vpn.network='vpn0'
|
||||
|
||||
delete firewall.vpntowan
|
||||
set firewall.vpntowan=forwarding
|
||||
set firewall.vpntowan.src='vpn'
|
||||
set firewall.vpntowan.dest='wan'
|
||||
|
||||
delete firewall.vpntolan
|
||||
set firewall.vpntolan=forwarding
|
||||
set firewall.vpntolan.src='vpn'
|
||||
set firewall.vpntolan.dest='lan'
|
||||
|
||||
delete firewall.lantovpn
|
||||
set firewall.lantovpn=forwarding
|
||||
set firewall.lantovpn.src='lan'
|
||||
set firewall.lantovpn.dest='vpn'
|
||||
|
||||
commit firewall
|
||||
EOF
|
||||
|
||||
if [ ! -f "/etc/openvpn/pki/ca.crt" ]; then
|
||||
sh /etc/openvpn/renewcert.sh 2>&1 >/dev/null
|
||||
fi
|
||||
|
||||
rm -f /tmp/luci-indexcache
|
||||
exit 0
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"luci-app-openvpn-server": {
|
||||
"description": "Grant UCI access for luci-app-openvpn-server",
|
||||
"read": {
|
||||
"uci": [ "openvpn" ]
|
||||
},
|
||||
"write": {
|
||||
"uci": [ "openvpn" ]
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user