Here comes the PoC.
Config changes
/etc/profile.d/download-wrapper-aliases.sh
alias curl="curl-wrapper"
alias wget="wget-wrapper"
# sudo will not use aliases unless https://linuxhandbook.com/run-alias-as-sudo/
alias sudo="sudo "
Append the following under /etc/bash.bashrc
#/etc/profile.d scripts are not loaded in interactive non-login shells (https://linuxhandbook.com/run-alias-as-sudo/)
if [ -d /etc/profile.d ]; then
for i in /etc/profile.d/*.sh; do
if [ -r $i ]; then
. $i
fi
done
unset i
fi
Scripts
/usr/bin/wget-wrapper
#!/bin/env bash
# wget-wrapper script around wget
# Goal is to give a chance to the user of knowing what is going to happen next, educate and explain what is different in Templates
#
# This wrapper script detects if the wget command was ran in a TemplateVM (Which by default is prohibited)
# In case the Template is trusted (No Network assigned), it warns the user to call wget-proxy instead and exits
# In case the Template has network assigned, it warns the user the template should not be trusted anymore and proceeds in 3 seconds
# In case we are not in a template, just add a warning and proceed with original wget call
#
#Depends on :
# this file being deployed in OS searchable path (eg: /usr/bin)
# alias being previously defined on the system prior of running wget.
# To test this:
# alias wget="wget-wrapper"
# To permanently define the alias for a user, add the alias in ~/.bashrc
if [ "$(qubesdb-read /type)" == "TemplateVM" ]; then
if ! $(qubesdb-read /qubes-gateway > /dev/null 2>&1); then
echo "You attempted to download a file with wget in a Template without direct internet access. (no network assigned)." >&2
echo "" >&2
echo "The attempted downloading command was: wget $@" >&2
echo "" >&2
echo "You either:" >&2
echo " 1- need to replace wget by wget-proxy in previous attempted shell command line (Recommended)." >&2
echo " 2- assign a Networking qube to this Template which should consequently be less trusted. (Untrusted)." >&2
exit 1
else
echo "You attempted to download a file with wget in a Template WITH DIRECT INTERNET ACCESS. (network assigned)." >&2
echo "" >&2
echo "The attempted downloading command was: wget $@" >&2
echo "" >&2
echo "Continuing in 3 seconds... Type CTRL+C to prevent the download now!" >&2
sleep 3
/usr/bin/wget "$@"
fi
else
echo "wget download attempt not in TemplateVM. Continuing..." >&2
/usr/bin/wget "$@"
fi
/usr/bin/curl-wrapper
#!/bin/env bash
# curl-wrapper script around curl
# Goal is to give a chance to the user of knowing what is going to happen next, educate and explain what is different in Templates
#
# This wrapper script detects if the curl command was ran in a TemplateVM (Which by default is prohibited)
# In case the Template is trusted (No Network assigned), it warns the user to call curl-proxy instead and exits
# In case the Template has network assigned, it warns the user the template should not be trusted anymore and proceeds in 3 seconds
# In case we are not in a template, just add a warning and proceed with original curl call
#
#Depends on :
# this file being deployed in OS searchable path (eg: /usr/bin)
# alias being previously defined on the system prior of running curl.
# To test this:
# alias curl="curl-wrapper"
# To permanently define the alias for a user, add the alias in ~/.bashrc
if [ "$(qubesdb-read /type)" == "TemplateVM" ]; then
if ! $(qubesdb-read /qubes-gateway > /dev/null 2>&1); then
echo "You attempted to download a file with curl in a Template without direct internet access. (no network assigned)." >&2
echo "" >&2
echo "The attempted downloading command was: curl $@" >&2
echo "" >&2
echo "You either:" >&2
echo " 1- need to replace curl by curl-proxy in previous attempted shell command line (Recommended)." >&2
echo " 2- assign a Networking qube to this Template which should consequently be less trusted. (Untrusted)." >&2
exit 1
else
echo "You attempted to download a file with curl in a Template WITH DIRECT INTERNET ACCESS. (network assigned)." >&2
echo "" >&2
echo "The attempted downloading command was: curl $@" >&2
echo "" >&2
echo "Continuing in 3 seconds... Type CTRL+C to prevent the download now!" >&2
sleep 3
/usr/bin/curl "$@"
fi
else
echo "curl download attempt not in TemplateVM. Continuing..." >&2
/usr/bin/curl "$@"
fi
/usr/bin/curl-proxy
#!/bin/env bash
curl --proxy http://127.0.0.1:8082/ --tlsv1.2 --proto =https --max-time 180 $@
/usr/bin/wget-proxy
#!/bin/env bash
https_proxy=http://127.0.0.1:8082/ http_proxy=http://127.0.0.1:8082/ wget --secure-protocol=TLSv1_2 --timeout=180 "$@"
Testing instructions
- Clone Template
- Deploy scripts
- Apply system wide changes above related to aliases (Should probably file a bug report @marmarek ?)
- Reproduce results
- Assign network to Template. Reproduce results
- Create qube based on previous cloned template. Reproduce results.
No network assigned to cloned Template use case:
user@debian-11:~$ alias
alias curl='curl-wrapper'
alias ls='ls --color=auto'
alias sudo='sudo '
alias wget='wget-wrapper'
Non-Networked Template: gpg key download of signal from user
user@debian-11:~$ wget -O- https://updates.signal.org/desktop/apt/keys.asc
You attempted to download a file with wget in a Template without direct internet access. (no network assigned).
The attempted downloading command was: wget -O- https://updates.signal.org/desktop/apt/keys.asc
You either:
1- need to replace wget by wget-proxy in previous attempted shell command line (Recommended).
2- assign a Networking qube to this Template which should consequently be less trusted. (Untrusted).
user@debian-11:~$ wget-proxy -O- https://updates.signal.org/desktop/apt/keys.asc | gpg --dearmor > signal-desktop-keyring.gpg
--2022-04-21 10:52:38-- https://updates.signal.org/desktop/apt/keys.asc
Connecting to 127.0.0.1:8082... connected.
Proxy request sent, awaiting response... 200 OK
Length: 3090 (3.0K) [application/pgp-signature]
Saving to: ‘STDOUT’
- 100%[=======================================================================>] 3.02K 18.1KB/s in 0.2s
2022-04-21 10:52:41 (18.1 KB/s) - written to stdout [3090/3090]
Non-Networked Template: gpg key download of session (sudo curl call per instructions) use case:
user@debian-11:~$ alias
alias curl='curl-wrapper'
alias ls='ls --color=auto'
alias sudo='sudo '
alias wget='wget-wrapper'
user@debian-11:~$ sudo curl -so /etc/apt/trusted.gpg.d/oxen.gpg https://deb.oxen.io/pub.gpg
You attempted to download a file with curl in a Template without direct internet access. (no network assigned).
The attempted downloading command was: curl /etc/apt/trusted.gpg.d/oxen.gpg https://deb.oxen.io/pub.gpg
You either:
1- need to replace curl by curl-proxy in previous attempted shell command line (Recommended).
2- assign a Networking qube to this Template which should consequently be less trusted. (Untrusted).
user@debian-11:~$ sudo curl-proxy -so /etc/apt/trusted.gpg.d/oxen.gpg https://deb.oxen.io/pub.gpg
user@debian-11:~$ ls -al /etc/apt/trusted.gpg.d/oxen.gpg
-rw-r--r-- 1 root root 2213 Apr 21 11:58 /etc/apt/trusted.gpg.d/oxen.gpg
Assigned network to Template use case:
Networked Template: Signal wget use case (normal user)
user@debian-11-networked:~$ wget -O- https://updates.signal.org/desktop/apt/keys.asc | gpg --dearmor > signal-desktop-keyring.gpg
You attempted to download a file with wget in a Template WITH DIRECT INTERNET ACCESS. (network assigned).
The attempted downloading command was: wget -O- https://updates.signal.org/desktop/apt/keys.asc
Continuing in 3 seconds... Type CTRL+C to prevent the download now!
--2022-04-21 12:01:23-- https://updates.signal.org/desktop/apt/keys.asc
Resolving updates.signal.org (updates.signal.org)... 172.64.155.131, 104.18.32.125, 2606:4700:4400::6812:207d, ...
Connecting to updates.signal.org (updates.signal.org)|172.64.155.131|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3090 (3.0K) [application/pgp-signature]
Saving to: ‘STDOUT’
- 100%[===================>] 3.02K --.-KB/s in 0s
2022-04-21 12:01:23 (13.0 MB/s) - written to stdout [3090/3090]
Networked Template: Session sudo curl use case (runs as root)
user@debian-11-networked:~$ sudo curl -so /etc/apt/trusted.gpg.d/oxen.gpg https://deb.oxen.io/pub.gpg
You attempted to download a file with curl in a Template WITH DIRECT INTERNET ACCESS. (network assigned).
The attempted downloading command was: curl -so /etc/apt/trusted.gpg.d/oxen.gpg https://deb.oxen.io/pub.gpg
Continuing in 3 seconds... Type CTRL+C to prevent the download now!
user@debian-11-networked:~$ ls -al /etc/apt/trusted.gpg.d/oxen.gpg
-rw-r--r-- 1 root root 2213 Apr 21 12:02 /etc/apt/trusted.gpg.d/oxen.gpg
curl and wget direct calls in Networked Templates
user@debian-11-networked:~$ wget
You attempted to download a file with wget in a Template WITH DIRECT INTERNET ACCESS. (network assigned).
The attempted downloading command was: wget
Continuing in 3 seconds... Type CTRL+C to prevent the download now!
wget: missing URL
Usage: wget [OPTION]... [URL]...
Try `wget --help' for more options.
user@debian-11-networked:~$ curl
You attempted to download a file with curl in a Template WITH DIRECT INTERNET ACCESS. (network assigned).
The attempted downloading command was: curl
Continuing in 3 seconds... Type CTRL+C to prevent the download now!
curl: try 'curl --help' or 'curl --manual' for more information
Normal Qube depending on that cloned template use case
user@wrapper-test:~$ wget
wget download attempt not in TemplateVM. Continuing...
wget: missing URL
Usage: wget [OPTION]... [URL]...
Try `wget --help' for more options.
user@wrapper-test:~$ curl
curl download attempt not in TemplateVM. Continuing...
curl: try 'curl --help' or 'curl --manual' for more information
Notes
@marmarek @adw @Sven @fsflover @Demi @deeplow : Am I making my point?
@Demi @marmarek: Fell upon two interesting bugs
- sudo cannot invoque aliases unless
alias sudo="sudo "
per How to Run an Alias With Sudo in Linux
- /etc/profile.d/* are ignored when using graphical shells (interactive, non-login shells: Why are scripts in /etc/profile.d/ being ignored (system-wide bash aliases)? )
This is why /etc/bash.bashrc
was modified to also source /etc/profile.d/*.sh
.
@marmarek @demi @fepitre : Qubes Bug/Feature?
Edit: Sorry for all the edits. I’m done now.
Edit2. I’m done for real, sorry. This is why writing documentation is so hard.