TorVirt
This commit is contained in:
parent
f1966465f2
commit
9a0e6e2f5a
31
README.md
31
README.md
|
@ -1,5 +1,5 @@
|
||||||
# Hide My Pussy !
|
# TorVirt
|
||||||
Whonix setup with KVM as workstation and a docker container as gateway.
|
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)
|
![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.
|
[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 ?
|
## 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 ?
|
## 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.
|
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):
|
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:
|
Clone the repo:
|
||||||
|
@ -48,11 +48,11 @@ __Don't continue if the verification fails !__
|
||||||
|
|
||||||
Configure your host:
|
Configure your host:
|
||||||
```
|
```
|
||||||
sudo ./hidemypussy.sh configure
|
sudo ./torvirt.sh configure
|
||||||
```
|
```
|
||||||
|
|
||||||
## Create the workstation
|
## 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__ ! \
|
Download the Kicksecure VM from https://www.whonix.org/wiki/Kicksecure/KVM. Don't forget to __verify OpenPGP signatures__ ! \
|
||||||
Then, extract the downloaded archive:
|
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
|
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:
|
Import the workstation VM:
|
||||||
```
|
```
|
||||||
sudo virsh define Kicksecure-hidemypussy.xml
|
sudo virsh define Kicksecure-torvirt.xml
|
||||||
```
|
```
|
||||||
|
|
||||||
## Start the gateway
|
## Start the gateway
|
||||||
```
|
```
|
||||||
sudo ./hidemypussy.sh start
|
sudo ./torvirt.sh start
|
||||||
```
|
```
|
||||||
|
|
||||||
## Start the workstation
|
## Start the workstation
|
||||||
The easiest way to start the workstation is through the `virt-manager` GUI. \
|
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)
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
FROM alpine:latest
|
FROM alpine:latest
|
||||||
RUN apk update
|
RUN apk update && apk upgrade
|
||||||
RUN apk add tor
|
RUN apk add tor
|
||||||
RUN adduser -D user
|
RUN adduser -D user
|
||||||
USER user
|
USER user
|
||||||
COPY torrc /etc/tor/torrc
|
COPY torrc /etc/tor/torrc
|
||||||
COPY wait.sh /home/user/wait.sh
|
COPY wait.sh /home/user/wait.sh
|
||||||
ENTRYPOINT ["/home/user/wait.sh", "tor"]
|
CMD ["/home/user/wait.sh", "tor"]
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
start_file="/home/user/start"
|
# wait for USR1
|
||||||
while [ ! -f $start_file ]; do
|
sleep infinity & PID=$!
|
||||||
sleep 1
|
trap "kill $PID" USR1
|
||||||
done
|
wait
|
||||||
|
|
||||||
exec $@
|
exec $@
|
||||||
|
|
|
@ -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
|
|
14
network.xml
14
network.xml
|
@ -1,9 +1,15 @@
|
||||||
<network>
|
<network xmlns:dnsmasq='http://libvirt.org/schemas/network/dnsmasq/1.0'>
|
||||||
<name>hidemypussy</name>
|
<name>torvirt</name>
|
||||||
<domain name="network"/>
|
<domain name="network"/>
|
||||||
<ip address="10.152.152.1" netmask="255.255.192.0">
|
<ip address="10.152.152.1" prefix="24">
|
||||||
<dhcp>
|
<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>
|
</dhcp>
|
||||||
</ip>
|
</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>
|
</network>
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 40 KiB |
|
@ -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
|
Loading…
Reference in New Issue