This commit is contained in:
Matéo Duparc 2023-05-25 22:12:53 +02:00
parent f1966465f2
commit 9a0e6e2f5a
Signed by: hardcoresushi
GPG Key ID: AFE384344A45E13A
8 changed files with 138 additions and 128 deletions

View File

@ -1,5 +1,5 @@
# Hide My Pussy !
Whonix setup with KVM as workstation and a docker container as gateway.
# TorVirt
Whonix-like setup with a [libvirt](https://libvirt.org) workstation and a docker container as the [Tor](https://torproject.org) gateway.
![Logo: KVM vers docker vers Tor](pictures/logo.jpg)
@ -7,7 +7,7 @@ Whonix setup with KVM as workstation and a docker container as gateway.
[Whonix](https://www.whonix.org) is a secure anonymization tool that creates a virtual machine in which all internet traffic is routed through [Tor](https://www.torproject.org/) via another virtual machine. These two VMs are connected in an internal virtual network. The only way for the workstation to access the Internet is to use the gateway, and thus anonymizing the network traffic. This allows you to run all kind of applications without worrying of IP leaks.
## What are the advatage of this project over original Whonix ?
Whonix uses one VM for the workstation and another VM for the tor gateway. If you don't have enough RAM, this may be resource expensive. With Hide my Pussy, you can improve the workstation performances by running the gateway inside a docker container instead of a full VM.
Whonix uses one VM for the workstation and another VM for the tor gateway. If you don't have enough RAM, this may be resource expensive. With TorVirt, you can improve the workstation performances by running the gateway inside a docker container instead of a full VM.
## Is it as secure as Whonix ?
Docker containers share the same kernel as the host. This means that if someone manages to exploit a software in the gateway container (such as the tor daemon) and then exploits a vulnerability in the kernel, he could gain access to the host's operating system. To mitigate this risk, the gateway container is started with `--cap-drop=ALL` and the only additional software installed is the tor daemon, which runs under normal user privileges.
@ -16,7 +16,7 @@ Docker containers share the same kernel as the host. This means that if someone
Install dependencies (debian-based):
```
sudo apt-get install virt-manager docker.io
sudo apt-get install virt-manager docker.io bridge-utils
```
Clone the repo:
@ -48,11 +48,11 @@ __Don't continue if the verification fails !__
Configure your host:
```
sudo ./hidemypussy.sh configure
sudo ./torvirt.sh configure
```
## Create the workstation
_In this tutorial, we will use the Kicksecure VM from the Whonix project. However, it's not strictly needed. You can use any other VM instead. For that, just configure your custom VM to use the network "hidemypussy"._
_In this tutorial, we will use the Kicksecure VM from the Whonix project. However, it's not strictly needed. You can use any other VM instead. For that, just configure your custom VM to use the network "torvirt"._
Download the Kicksecure VM from https://www.whonix.org/wiki/Kicksecure/KVM. Don't forget to __verify OpenPGP signatures__ ! \
Then, extract the downloaded archive:
@ -63,28 +63,19 @@ Move the workstation image to the libvirt's images folder:
```
sudo mv Kicksecure*.qcow2 /var/lib/libvirt/images/Kicksecure.qcow2
```
Edit the workstation XML file to use the hidemypussy network:
Edit the workstation XML file to use the torvirt network:
```
sed "s/network='default'/network='hidemypussy'/g" Kicksecure*.xml > Kicksecure-hidemypussy.xml
sed "s/network='default'/network='torvirt'/g" Kicksecure*.xml > Kicksecure-torvirt.xml
```
Import the workstation VM:
```
sudo virsh define Kicksecure-hidemypussy.xml
sudo virsh define Kicksecure-torvirt.xml
```
## Start the gateway
```
sudo ./hidemypussy.sh start
sudo ./torvirt.sh start
```
## Start the workstation
The easiest way to start the workstation is through the `virt-manager` GUI. \
Once started, you will need to configure the VM to use the tor gateway as default gateway and default DNS server. The default IP for the gateway is `10.152.152.10`. You can get it by running `sudo docker exec hidemypussy ifconfig vmnet-cont | awk '/inet addr/{print substr($2,6)}'`. \
Inside the workstation, run:
```
sudo echo "nameserver 10.152.152.10" > /etc/resolv.conf
sudo ip route add default via 10.152.152.10
```
To make this changes persistent, you can make a script that runs these 2 commands at startup or manually configure the interface in Network-Manager:
![Network-Manager screenshot in manual configuration with gateway and DNS server set to the gateway container's IP](pictures/NetworkManager.png)
The easiest way to start the workstation is through the `virt-manager` GUI.

View File

@ -1,8 +1,8 @@
FROM alpine:latest
RUN apk update
RUN apk update && apk upgrade
RUN apk add tor
RUN adduser -D user
USER user
COPY torrc /etc/tor/torrc
COPY wait.sh /home/user/wait.sh
ENTRYPOINT ["/home/user/wait.sh", "tor"]
CMD ["/home/user/wait.sh", "tor"]

View File

@ -2,4 +2,4 @@ VirtualAddrNetworkIPv4 10.192.0.0/10
AutomapHostsOnResolve 1
SocksPort 0
TransPort 10.152.152.10:9040 IsolateClientAddr IsolateClientProtocol IsolateDestAddr IsolateDestPort
DNSPort 10.152.152.10:5353
DNSPort 10.152.152.10:5353

View File

@ -1,7 +1,8 @@
#!/bin/sh
start_file="/home/user/start"
while [ ! -f $start_file ]; do
sleep 1
done
# wait for USR1
sleep infinity & PID=$!
trap "kill $PID" USR1
wait
exec $@

View File

@ -1,97 +0,0 @@
#!/bin/bash
project_name="hidemypussy"
img_name=$project_name
cont_name=$project_name
docker_folder="gateway"
network_file="network.xml"
network=$project_name
tor_trans_port="9040"
tor_dns_port="5353"
tor_virt_addr="10.192.0.0/10"
gtw_ip="10.152.152.10/18"
start_file="/home/user/start"
veth_host="vmnet-host"
veth_cont="vmnet-cont"
print_help() {
echo -e "Usage: $0 <action>
ACTIONS:
- c, configure Install dependencies, configure network and build gateway docker image
- s, start Start the gateway
"
}
virsh_get_field() {
echo $(virsh net-info $network | grep $1 | tr -s " " | cut -d " " -f 2)
}
if [ "$#" -eq 0 ]; then
print_help
elif [ "$EUID" -ne 0 ]; then
echo "Error: root access required"
else
case $1 in
"s" | "start")
#check whether network and gateway have been configured
if [ -z "$(virsh net-list --all | grep $network)" ]; then
echo "Error: network $network not found. Did you run \"$0 configure\" first ?"
exit
elif [ -z "$(docker images | grep $img_name)" ]; then
echo "Error: docker image $img_name not found. Did you run \"$0 configure\" first ?"
exit
fi
if [ "$(docker ps -q -f name=$cont_name)" ]; then
echo "Error: conatiner $cont_name is already running"
exit
elif [ "$(docker ps -aq -f status=exited -f name=$cont_name)" ]; then
docker rm $cont_name
fi
#start $network
network_started=$(virsh_get_field "Active")
if [ $network_started = "no" ]; then
virsh net-start $network
fi
brif=$(virsh_get_field "Bridge")
#configure veth interfaces
ip link add $veth_cont type veth peer name $veth_host
brctl addif $brif $veth_host
ip link set $veth_host up
#start gateway on wait.sh
docker run --rm -itd --cap-drop=ALL --name $cont_name $img_name
pid=$(docker inspect -f '{{.State.Pid}}' $cont_name)
#setup gateway networing inside $network
ip link set netns $pid dev $veth_cont
nsenter -t $pid -n ip link set $veth_cont up
nsenter -t $pid -n ip addr add $gtw_ip dev $veth_cont
#allow *.onion
nsenter -t $pid -n iptables -t nat -A PREROUTING -i $veth_cont -p tcp -d $tor_virt_addr --syn -j REDIRECT --to-ports $tor_trans_port
#redirect DNS to tor
nsenter -t $pid -n iptables -t nat -A PREROUTING -i $veth_cont -p udp --dport 53 -j REDIRECT --to-ports $tor_dns_port
nsenter -t $pid -n iptables -t nat -A PREROUTING -i $veth_cont -p udp --dport $tor_dns_port -j REDIRECT --to-ports $tor_dns_port
#redirect TCP to tor
nsenter -t $pid -n iptables -t nat -A PREROUTING -i $veth_cont -p tcp --syn -j REDIRECT --to-ports $tor_trans_port
#start tor
docker exec $cont_name touch $start_file
docker attach $cont_name
;;
"c" | "configure")
dockerfile="$docker_folder/Dockerfile"
if [ ! -f $network_file ]; then
echo "Error: $network_file not found"
exit
elif [ ! -f $dockerfile ]; then
echo "Error: $dockerfile not found"
exit
fi
virsh net-define $network_file
pushd $docker_folder
docker build -t $img_name .
;;
*)
echo "Unkown action: $1"
print_help
;;
esac
fi

View File

@ -1,9 +1,15 @@
<network>
<name>hidemypussy</name>
<network xmlns:dnsmasq='http://libvirt.org/schemas/network/dnsmasq/1.0'>
<name>torvirt</name>
<domain name="network"/>
<ip address="10.152.152.1" netmask="255.255.192.0">
<ip address="10.152.152.1" prefix="24">
<dhcp>
<range start="10.152.152.1" end="10.152.152.253"/>
<range start="10.152.152.2" end="10.152.152.9"/>
<range start="10.152.152.11" end="10.152.152.254"/>
</dhcp>
</ip>
<dnsmasq:options>
<dnsmasq:option value="dhcp-option=option:router,10.152.152.10"/>
<dnsmasq:option value="dhcp-option=option:dns-server,10.152.152.10"/>
</dnsmasq:options>
<port isolated="yes"/>
</network>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

109
torvirt Executable file
View File

@ -0,0 +1,109 @@
#!/bin/bash
set -e
project_name="torvirt"
img_name=$project_name
container_name=$project_name
docker_folder="gateway"
network_file="network.xml"
network=$project_name
tor_trans_port="9040"
tor_dns_port="5353"
tor_virt_addr="10.192.0.0/10"
gtw_ip="10.152.152.10/18"
veth_host="$project_name-host"
veth_gw="$project_name-gw"
ERROR_INVALID_ACTION=1
ERROR_ALREADY_CONFIGURED=2
ERROR_NOT_CONFIGURED=3
ERROR_ALREADY_RUNNING=4
print_help() {
echo -e "Usage: $0 <action>
ACTIONS:
c, configure Install dependencies, configure network and build gateway docker image
s, start Start the gateway
"
}
exit_with() {
echo $2 >&2
exit $1
}
virsh_get_field() {
virsh net-info $network |awk "/^$1:/{print \$2}"
}
if [ "$#" -eq 0 ]; then
print_help
exit
fi
case $1 in
"s" | "start")
# check whether network and gateway have been configured
if [ -z "$(virsh net-list --all | grep $network)" ]; then
exit_with $ERROR_NOT_CONFIGURED "Error: network $network not found. Did you run \"$project_name configure\" ?"
fi
output=$(docker images ls -q -f reference=$img_name)
if [ -z "$output" ]; then
exit_with $ERROR_NOT_CONFIGURED "Error: docker image $img_name not found. Did you run \"$project_name configure\" first ?"
fi
output=$(docker ps -q -f name=$container_name)
if [ "$output" ]; then
exit_with $ERROR_ALREADY_RUNNING "Error: conatiner $container_name is already running"
fi
output=$(docker ps -aq -f status=exited -f name=$container_name)
if [ "$output" ]; then
docker rm $container_name
fi
# start $network
network_started=$(virsh_get_field "Active")
if [ $network_started = "no" ]; then
virsh net-start $network
fi
brif=$(virsh_get_field "Bridge")
# configure veth interfaces
if ip link show $veth_host >/dev/null 2>/dev/null; then
ip link del $veth_host
fi
ip link add $veth_gw type veth peer name $veth_host
brctl addif $brif $veth_host
ip link set $veth_host up
# start gateway on wait.sh
docker run --rm -itd --cap-drop=ALL --name $container_name $img_name >/dev/null
pid=$(docker inspect -f '{{.State.Pid}}' $container_name)
# setup gateway networing inside $network
ip link set netns $pid dev $veth_gw
nsenter -t $pid -n ip link set $veth_gw up
nsenter -t $pid -n ip addr add $gtw_ip dev $veth_gw
# allow *.onion
nsenter -t $pid -n iptables -t nat -A PREROUTING -i $veth_gw -p tcp -d $tor_virt_addr --syn -j REDIRECT --to-ports $tor_trans_port
# redirect DNS to tor
nsenter -t $pid -n iptables -t nat -A PREROUTING -i $veth_gw -p udp --dport 53 -j REDIRECT --to-ports $tor_dns_port
nsenter -t $pid -n iptables -t nat -A PREROUTING -i $veth_gw -p udp --dport $tor_dns_port -j REDIRECT --to-ports $tor_dns_port
# redirect TCP to tor
nsenter -t $pid -n iptables -t nat -A PREROUTING -i $veth_gw -p tcp --syn -j REDIRECT --to-ports $tor_trans_port
# start tor
docker kill -s USR1 $container_name >/dev/null
docker attach $container_name
;;
"c" | "configure")
if virsh net-info $network >/dev/null 2>/dev/null; then
exit_with $ERROR_ALREADY_CONFIGURED "Error: network $network already exists."
fi
output=$(docker images ls -q -f reference=$img_name)
if [ "$output" ]; then
exit_with $ERROR_ALREADY_CONFIGURED "Error: image $img_name already exists"
fi
virsh net-define $network_file
cd $docker_folder && docker build -t $img_name .
;;
*)
print_help
exit_with $ERROR_INVALID_ACTION "Unkown action: $1"
;;
esac