v1.3. New options: full proxy mode, downloading blacklist through proxy.

This commit is contained in:
gSpot
2023-08-29 17:43:52 +03:00
parent c8e8832a3d
commit 46944b8c3f
14 changed files with 146 additions and 22 deletions
+1 -1
View File
@@ -4,7 +4,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.2-3
PKG_VERSION:=1.3-0
LUCI_TITLE:=LuCI support for ruantiblock
LUCI_DEPENDS:=+ruantiblock
LUCI_PKGARCH:=all
@@ -47,7 +47,6 @@ return view.extend({
if(data.rules.nftables && data.rules.nftables.length > 1) {
for(let i of data.rules.nftables) {
if(!i.rule) continue;
let set, bytes;
i.rule.expr.forEach(e => {
if(e.match && e.match.left && e.match.left.payload) {
@@ -287,7 +286,7 @@ return view.extend({
'class' : 'td left',
'data-title': _('Match-set'),
}, set + ((set.length >= 1) ? (
' (' + set.replace(/^c/, 'CIDR').replace(/^i/, 'IP').replace(/^d/, 'dnsmasq').replace(/^bi/, 'bypass IP').replace(/^bd/, 'bypass dnsmasq') + ')'
' (' + set.replace(/^c/, 'CIDR').replace(/^i/, 'IP').replace(/^d/, 'dnsmasq').replace(/^bi/, 'bypass IP').replace(/^bd/, 'bypass dnsmasq').replace(/^fproxy/, 'full proxy') + ')'
) : '')),
E('td', {
'class' : 'td left',
@@ -162,7 +162,18 @@ return view.extend({
// ALLOWED_HOSTS_LIST
o = s.taboption('main_settings', form.DynamicList, 'allowed_hosts_list',
_('IP addresses of hosts'));
_('IP addresses for host filter'));
o.datatype = "ip4addr";
// ENABLE_FPROXY
o = s.taboption('main_settings', form.Flag, 'enable_fproxy',
_('Enable full proxy mode'));
o.description = _('All traffic of the specified hosts passes through the proxy, without a blacklist');
o.rmempty = false;
// FPROXY_LIST
o = s.taboption('main_settings', form.DynamicList, 'fproxy_list',
_('IP addresses for full proxy mode'));
o.datatype = "ip4addr";
@@ -254,6 +265,13 @@ return view.extend({
Object.entries(this.parsers).forEach(
e => bllist_module.value(e[1], e[0]));
// ENABLE_BLLIST_PROXY
o = s.taboption('blacklist_tab', form.Flag, 'enable_bllist_proxy',
_('Downloading a blacklist via proxy'), _('Turn on if blacklist source is blocked'));
o.rmempty = false;
o.default = 0;
o.depends({ bllist_preset: '', '!reverse': true });
// ADD_USER_ENTRIES
o = s.taboption('blacklist_tab', form.Flag, 'add_user_entries',
_('Enable user entries'), _("Add user entries to the blacklist when updating"));
+17 -2
View File
@@ -31,6 +31,9 @@ msgstr "Все записи, кроме соответствующих шабл
msgid "All hosts except listed"
msgstr "Все хосты, кроме перечисленных"
msgid "All traffic of the specified hosts passes through the proxy, without a blacklist"
msgstr "Весь трафик указанных хостов проходит через прокси, без применения блэклиста"
msgid "Allows you to limit the hosts that are allowed to bypass blocking"
msgstr "Позволяет ограничить хосты, которым разрешено обходить блокировки"
@@ -110,6 +113,9 @@ msgstr "Ошибка загрузки"
msgid "Download log"
msgstr "Скачать лог"
msgid "Downloading a blacklist via proxy"
msgstr "Скачивать блэклист через прокси"
msgid "Edit"
msgstr "Изменить"
@@ -128,6 +134,9 @@ msgstr "Включить IP фильтр"
msgid "Enable exclusion list"
msgstr "Включить список исключений"
msgid "Enable full proxy mode"
msgstr "Включить режим полного прокси"
msgid "Enable user entries"
msgstr "Включить записи пользователя"
@@ -176,8 +185,11 @@ msgstr "Если от источника получено меньше указ
msgid "IP address"
msgstr "IP-адрес"
msgid "IP addresses of hosts"
msgstr "IP-адреса хостов"
msgid "IP addresses for full proxy mode"
msgstr "IP-адреса для режима полного прокси"
msgid "IP addresses for host filter"
msgstr "IP-адреса для фильтра хостов"
msgid "IP filter"
msgstr "Фильтр IP"
@@ -437,6 +449,9 @@ msgstr "TCP порт прозрачного прокси"
msgid "Transparent proxy UDP port"
msgstr "UDP порт прозрачного прокси"
msgid "Turn on if blacklist source is blocked"
msgstr "Включите, если источник блэклиста заблокирован"
msgid "Type an expression..."
msgstr "Введите выражение..."
@@ -19,6 +19,9 @@ msgstr ""
msgid "All hosts except listed"
msgstr ""
msgid "All traffic of the specified hosts passes through the proxy, without a blacklist"
msgstr ""
msgid "Apply"
msgstr ""
@@ -94,6 +97,10 @@ msgstr ""
msgid "Download log"
msgstr ""
msgid "Downloading a blacklist via proxy"
msgstr ""
msgid "Edit"
msgstr ""
@@ -111,6 +118,9 @@ msgstr ""
msgid "Enable exclusion list"
msgstr ""
msgid "Enable full proxy mode"
msgstr ""
msgid "Enable user entries"
msgstr ""
@@ -159,7 +169,10 @@ msgstr ""
msgid "IP address"
msgstr ""
msgid "IP addresses of hosts"
msgid "IP addresses for full proxy mode"
msgstr ""
msgid "IP addresses for host filter"
msgstr ""
msgid "IP filter"
@@ -401,6 +414,9 @@ msgstr ""
msgid "Transparent proxy UDP port"
msgstr ""
msgid "Turn on if blacklist source is blocked"
msgstr ""
msgid "Type an expression..."
msgstr ""
msgid "Unable to execute or read contents"
+1 -1
View File
@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=ruantiblock-mod-lua
PKG_VERSION:=1.2
PKG_VERSION:=1.3
PKG_RELEASE:=0
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt>
+1 -1
View File
@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=ruantiblock-mod-py
PKG_VERSION:=1.2
PKG_VERSION:=1.3
PKG_RELEASE:=0
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt>
+2 -2
View File
@@ -5,8 +5,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=ruantiblock
PKG_VERSION:=1.2
PKG_RELEASE:=3
PKG_VERSION:=1.3
PKG_RELEASE:=0
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt>
include $(INCLUDE_DIR)/package.mk
+2
View File
@@ -5,6 +5,8 @@ config main 'config'
option nftset_clear_sets '1'
option allowed_hosts_mode '0'
option bypass_mode '0'
option enable_fproxy '0'
option enable_bllist_proxy '0'
option if_vpn 'tun0'
option tor_trans_port '9040'
option onion_dns_addr '127.0.0.1#9053'
@@ -80,6 +80,16 @@ BYPASS_MODE=0
BYPASS_ENTRIES_DNS=""
### Файл исключаемых записей
BYPASS_ENTRIES_FILE="/etc/ruantiblock/bypass_entries"
### Включение режима полного прокси (0 - выкл, 1 - вкл)
ENABLE_FPROXY=0
### Список IP адресов хостов для режима полного прокси, через пробел (прим.: 192.168.0.10 192.168.0.15)
FPROXY_LIST=""
### Список приватных сетей для режима полного прокси, через пробел
FPROXY_PRIVATE_NETS="192.168.0.0/16 172.16.0.0/12 10.0.0.0/8"
### Скачивать блэклисты через прокси
ENABLE_BLLIST_PROXY=0
### Список хостов источников блэклиста
BLLIST_HOSTS="reestr.rublacklist.net raw.githubusercontent.com antifilter.download"
### Кол-во попыток обновления блэклиста (в случае неудачи)
MODULE_RUN_ATTEMPTS=3
### Таймаут между попытками обновления
+59 -6
View File
@@ -95,6 +95,16 @@ export BYPASS_MODE=0
export BYPASS_ENTRIES_DNS=""
### Файл исключаемых записей
export BYPASS_ENTRIES_FILE="${CONFIG_DIR}/bypass_entries"
### Включение режима полного прокси (0 - выкл, 1 - вкл)
export ENABLE_FPROXY=0
### Список IP адресов хостов для режима полного прокси, через пробел (прим.: 192.168.0.10 192.168.0.15)
export FPROXY_LIST=""
### Список приватных сетей для режима полного прокси, через пробел
export FPROXY_PRIVATE_NETS="192.168.0.0/16 172.16.0.0/12 10.0.0.0/8"
### Скачивать блэклисты через прокси
export ENABLE_BLLIST_PROXY=0
### Список хостов источников блэклиста
export BLLIST_HOSTS="reestr.rublacklist.net raw.githubusercontent.com antifilter.download"
### Кол-во попыток обновления блэклиста (в случае неудачи)
export MODULE_RUN_ATTEMPTS=3
### Таймаут между попытками обновления
@@ -193,12 +203,20 @@ if [ $? -ne 0 ]; then
exit 1
fi
WGET_PARAMS="--no-check-certificate -q -O"
NSLOOKUP_CMD=`which nslookup`
if [ $? -ne 0 ]; then
echo " Error! Nslookup doesn't exists" >&2
exit 1
fi
export IP_DATA_FILE="${DATA_DIR}/${NAME}.ip"
export NFT_TABLE="ip r"
export NFT_TABLE_DNSMASQ="4#ip#r"
export NFTSET_ALLOWED_HOSTS="allowed_ip"
export NFTSET_BYPASS_IP="bi"
export NFTSET_BYPASS_FQDN="bd"
export NFTSET_FPROXY="fproxy"
export NFTSET_FPROXY_PRIVATE="fproxy_private"
export NFTSET_BLLIST_PROXY="bllist_proxy"
export NFTSET_ONION="onion"
export NFTSET_CIDR="c"
export NFTSET_IP="i"
@@ -206,6 +224,9 @@ export NFTSET_DNSMASQ="d"
export NFTSET_ALLOWED_HOSTS_TYPE="ipv4_addr"
export NFTSET_BYPASS_IP_TYPE="ipv4_addr"
export NFTSET_BYPASS_FQDN_TYPE="ipv4_addr"
export NFTSET_FPROXY_TYPE="ipv4_addr"
export NFTSET_FPROXY_PRIVATE_TYPE="ipv4_addr"
export NFTSET_BLLIST_PROXY_TYPE="ipv4_addr"
export NFTSET_CIDR_TYPE="ipv4_addr"
export NFTSET_IP_TYPE="ipv4_addr"
export NFTSET_DNSMASQ_TYPE="ipv4_addr"
@@ -306,19 +327,51 @@ FlushNftSets() {
done
}
FormatNftSetElemsList() {
printf "$1" | $AWK_CMD '{gsub(/[ ]+/, ",", $0); printf $0;}'
}
AddNftSets() {
local _allowed_hosts _bypass_ips
local _allowed_hosts _bypass_ips _fproxy_hosts _fproxy_private
$NFT_CMD add set $NFT_TABLE "$NFTSET_CIDR" { type "$NFTSET_CIDR_TYPE"\; size $NFTSET_MAXELEM_CIDR\; policy "$NFTSET_POLICY_CIDR"\; flags interval\; auto-merge\; }
$NFT_CMD add set $NFT_TABLE "$NFTSET_IP" { type "$NFTSET_IP_TYPE"\; size $NFTSET_MAXELEM_IP\; policy "$NFTSET_POLICY_IP"\; flags dynamic\; }
$NFT_CMD add set $NFT_TABLE "$NFTSET_DNSMASQ" { type "$NFTSET_DNSMASQ_TYPE"\; size $NFTSET_MAXELEM_DNSMASQ\; policy "$NFTSET_POLICY_DNSMASQ"\; flags dynamic,timeout\; timeout "$NFTSET_DNSMASQ_TIMEOUT"\; }
$NFT_CMD add set $NFT_TABLE "$NFTSET_ONION" { type "$NFTSET_DNSMASQ_TYPE"\; size $NFTSET_MAXELEM_DNSMASQ\; policy "$NFTSET_POLICY_DNSMASQ"\; flags dynamic,timeout\; timeout "$NFTSET_DNSMASQ_TIMEOUT"\; }
$NFT_CMD add set $NFT_TABLE "$NFTSET_ALLOWED_HOSTS" { type "$NFTSET_ALLOWED_HOSTS_TYPE"\; policy "$NFTSET_POLICY_CIDR"\; flags interval\; auto-merge\; }
_allowed_hosts=`printf "$ALLOWED_HOSTS_LIST" | $AWK_CMD '{gsub(/[ ]+/, ",", $0); printf $0;}'`
_allowed_hosts=`FormatNftSetElemsList "$ALLOWED_HOSTS_LIST"`
if [ -n "$_allowed_hosts" ]; then
$NFT_CMD add element $NFT_TABLE "$NFTSET_ALLOWED_HOSTS" { "$_allowed_hosts" }
fi
$NFT_CMD add set $NFT_TABLE "$NFTSET_BYPASS_IP" { type "$NFTSET_BYPASS_IP_TYPE"\; size $NFTSET_MAXELEM_BYPASS_IP\; policy "$NFTSET_POLICY_CIDR"\; flags interval\; auto-merge\; }
$NFT_CMD add set $NFT_TABLE "$NFTSET_BYPASS_FQDN" { type "$NFTSET_BYPASS_FQDN_TYPE"\; size $NFTSET_MAXELEM_BYPASS_FQDN\; policy "$NFTSET_POLICY_DNSMASQ"\; flags dynamic,timeout\; timeout "$NFTSET_DNSMASQ_TIMEOUT"\; }
$NFT_CMD add set $NFT_TABLE "$NFTSET_FPROXY" { type "$NFTSET_FPROXY_TYPE"\; policy "$NFTSET_POLICY_CIDR"\; flags interval\; auto-merge\; }
_fproxy_hosts=`FormatNftSetElemsList "$FPROXY_LIST"`
if [ -n "$_fproxy_hosts" ]; then
$NFT_CMD add element $NFT_TABLE "$NFTSET_FPROXY" { "$_fproxy_hosts" }
fi
$NFT_CMD add set $NFT_TABLE "$NFTSET_FPROXY_PRIVATE" { type "$NFTSET_FPROXY_PRIVATE_TYPE"\; policy "$NFTSET_POLICY_CIDR"\; flags interval\; auto-merge\; }
_fproxy_private=`FormatNftSetElemsList "$FPROXY_PRIVATE_NETS"`
if [ -n "$_fproxy_private" ]; then
$NFT_CMD add element $NFT_TABLE "$NFTSET_FPROXY_PRIVATE" { "$_fproxy_private" }
fi
$NFT_CMD add set $NFT_TABLE "$NFTSET_BLLIST_PROXY" { type "$NFTSET_BLLIST_PROXY_TYPE"\; policy "$NFTSET_POLICY_IP"\; flags dynamic\; }
}
UpdateBllistProxySet() {
local _ip_string=""
FlushNftSets "$NFTSET_BLLIST_PROXY"
for host in $BLLIST_HOSTS
do
if printf "$host" | $AWK_CMD '{exit ($0 ~ /^([0-9]{1,3}.){3}[0-9]{1,3}$/) ? 0 : 1}'; then
_ip_string="${_ip_string}${host} "
else
_ip_string="${_ip_string}`$NSLOOKUP_CMD $host | $AWK_CMD '/^Address: ([0-9]{1,3}.){3}[0-9]{1,3}$/ {printf $2" "}'`"
fi
done
_ip_string=`FormatNftSetElemsList "$_ip_string"`
if [ -n "$_ip_string" ]; then
$NFT_CMD add element $NFT_TABLE "$NFTSET_BLLIST_PROXY" { "$_ip_string" }
fi
}
UpdateBllistSets() {
@@ -339,9 +392,6 @@ UpdateBllistSets() {
AddNftRules() {
NftMainAdd
if [ "$PROXY_LOCAL_CLIENTS" = "1" ]; then
NftLocalClientsAdd
fi
}
DeleteNftRules() {
@@ -356,7 +406,7 @@ SetNetConfig() {
DropNetConfig() {
DeleteNftRules
FlushNftSets "$NFTSET_ALLOWED_HOSTS" "$NFTSET_BYPASS_IP" "$NFTSET_BYPASS_FQDN" "$NFTSET_CIDR" "$NFTSET_IP" "$NFTSET_DNSMASQ" "$NFTSET_ONION"
FlushNftSets "$NFTSET_ALLOWED_HOSTS" "$NFTSET_FPROXY" "$NFTSET_FPROXY_PRIVATE" "$NFTSET_BLLIST_PROXY" "$NFTSET_BYPASS_IP" "$NFTSET_BYPASS_FQDN" "$NFTSET_CIDR" "$NFTSET_IP" "$NFTSET_DNSMASQ" "$NFTSET_ONION"
}
DestroyNetConfig() {
@@ -515,6 +565,9 @@ GetDataFiles() {
if [ -n "$BLLIST_PRESET" -a -n "$BLLIST_MODULE" ]; then
while :
do
if [ "$ENABLE_BLLIST_PROXY" = "1" ]; then
UpdateBllistProxySet
fi
$BLLIST_MODULE
_return_code=$?
[ $_return_code -eq 0 ] && break
@@ -1,6 +1,6 @@
AWK_CMD="awk"
UCI_SECTION="ruantiblock.config"
UCI_VARS="proxy_mode proxy_local_clients nftset_clear_sets allowed_hosts_mode allowed_hosts_list bypass_mode bypass_entries_dns if_vpn tor_trans_port onion_dns_addr t_proxy_port_tcp t_proxy_port_udp t_proxy_allow_udp add_user_entries user_entries_dns enable_logging bllist_min_entries bllist_module bllist_preset bllist_ip_limit bllist_gr_excluded_nets bllist_summarize_ip bllist_summarize_cidr bllist_ip_filter bllist_ip_filter_type bllist_sd_limit bllist_gr_excluded_sld bllist_fqdn_filter bllist_fqdn_filter_type bllist_enable_idn bllist_alt_nslookup bllist_alt_dns_addr update_at_startup"
UCI_VARS="proxy_mode proxy_local_clients nftset_clear_sets allowed_hosts_mode allowed_hosts_list bypass_mode bypass_entries_dns enable_fproxy fproxy_list enable_bllist_proxy if_vpn tor_trans_port onion_dns_addr t_proxy_port_tcp t_proxy_port_udp t_proxy_allow_udp add_user_entries user_entries_dns enable_logging bllist_min_entries bllist_module bllist_preset bllist_ip_limit bllist_gr_excluded_nets bllist_summarize_ip bllist_summarize_cidr bllist_ip_filter bllist_ip_filter_type bllist_sd_limit bllist_gr_excluded_sld bllist_fqdn_filter bllist_fqdn_filter_type bllist_enable_idn bllist_alt_nslookup bllist_alt_dns_addr update_at_startup"
eval `uci show "$UCI_SECTION" | $AWK_CMD -F "=" -v UCI_VARS="$UCI_VARS" '
BEGIN {
@@ -1,6 +1,7 @@
IP_CMD="ip"
NFT_ALLOWED_HOSTS_CHAIN="allowed_hosts"
NFT_BLLIST_CHAIN="blacklist"
NFT_FPROXY_FILTER="fproxy_filter"
NFT_DNSMASQ_TIMEOUT_UPDATE_CHAIN="dnsmasq_timeout_update"
NFT_ACTION_CHAIN="action"
NFT_LOCAL_CLIENTS_CHAIN="local_clients"
@@ -69,9 +70,12 @@ NftMainAdd() {
local _set
$NFT_CMD add chain $NFT_TABLE "$NFT_LOCAL_CLIENTS_CHAIN" { $LOCAL_CLIENTS_CHAIN_TYPE }
$NFT_CMD add chain $NFT_TABLE "$NFT_ACTION_CHAIN"
$NFT_CMD add chain $NFT_TABLE "$NFT_FPROXY_FILTER"
$NFT_CMD add chain $NFT_TABLE "$NFT_DNSMASQ_TIMEOUT_UPDATE_CHAIN"
$NFT_CMD add chain $NFT_TABLE "$NFT_BLLIST_CHAIN"
$NFT_CMD add chain $NFT_TABLE "$NFT_ALLOWED_HOSTS_CHAIN" { $MAIN_CHAIN_TYPE }
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE $NFT_FPROXY_FILTER ip daddr "@${NFTSET_FPROXY_PRIVATE}" return
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_FPROXY_FILTER" jump "$NFT_ACTION_CHAIN"
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_DNSMASQ_TIMEOUT_UPDATE_CHAIN" ct state new set update ip daddr "@${NFTSET_DNSMASQ}"
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_DNSMASQ_TIMEOUT_UPDATE_CHAIN" jump "$NFT_ACTION_CHAIN"
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_ALLOWED_HOSTS_CHAIN" $NFT_ALLOWED_HOSTS_EXPR
@@ -86,6 +90,9 @@ NftMainAdd() {
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_ACTION_CHAIN" tcp dport { 0-65535 } redirect to $TOR_TRANS_PORT
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_BLLIST_CHAIN" ip daddr "@${NFTSET_ONION}" counter goto "$NFT_ACTION_CHAIN"
fi
if [ "$ENABLE_FPROXY" = "1" ]; then
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_BLLIST_CHAIN" ip saddr "@${NFTSET_FPROXY}" counter goto "$NFT_FPROXY_FILTER"
fi
if [ "$BYPASS_MODE" = "1" ]; then
for _set in "$NFTSET_BYPASS_IP" "$NFTSET_BYPASS_FQDN"
do
@@ -100,6 +107,12 @@ NftMainAdd() {
if [ "$PROXY_MODE" = "2" ]; then
NftVpnRouteAdd
fi
if [ "$ENABLE_BLLIST_PROXY" = "1" ]; then
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_LOCAL_CLIENTS_CHAIN" ip daddr "@${NFTSET_BLLIST_PROXY}" counter goto "$NFT_ACTION_CHAIN"
fi
if [ "$PROXY_LOCAL_CLIENTS" = "1" ]; then
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_LOCAL_CLIENTS_CHAIN" jump "$NFT_BLLIST_CHAIN"
fi
}
NftMainDelete() {
@@ -111,15 +124,13 @@ NftMainDelete() {
$NFT_CMD delete chain $NFT_TABLE "$NFT_BLLIST_CHAIN"
$NFT_CMD flush chain $NFT_TABLE "$NFT_DNSMASQ_TIMEOUT_UPDATE_CHAIN"
$NFT_CMD delete chain $NFT_TABLE "$NFT_DNSMASQ_TIMEOUT_UPDATE_CHAIN"
$NFT_CMD flush chain $NFT_TABLE "$NFT_FPROXY_FILTER"
$NFT_CMD delete chain $NFT_TABLE "$NFT_FPROXY_FILTER"
$NFT_CMD flush chain $NFT_TABLE "$NFT_ACTION_CHAIN"
$NFT_CMD delete chain $NFT_TABLE "$NFT_ACTION_CHAIN"
NftVpnRouteDelete 2> /dev/null
}
NftLocalClientsAdd() {
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_LOCAL_CLIENTS_CHAIN" jump "$NFT_BLLIST_CHAIN"
}
NftListBllistChain() {
$NFT_CMD -t list chain $NFT_TABLE "$NFT_BLLIST_CHAIN"
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

After

Width:  |  Height:  |  Size: 122 KiB