Skip to content

Commit b19b27b

Browse files
committed
First Commit
Signed-off-by: Marc Ahlgrim <[email protected]>
1 parent e16df35 commit b19b27b

File tree

11 files changed

+561
-0
lines changed

11 files changed

+561
-0
lines changed

README

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
## example.com domain on Proxmox
2+
3+
### What?
4+
5+
With these scripts you can install a complete example.com domain for testing purposes on your proxmox server. This includes:
6+
7+
1. A client machine running a graphical MATE environment as entry point that can be accessed over RDP with the following software on it:
8+
- a Firefox Browser with pre-loaded certificates
9+
- Thunderbird Mail client, pre-loaded
10+
2. An OpenWrt Router as exit point
11+
3. DNS (running on dnsmasq on the OpenWrt Router) for the example.com domain
12+
4. A Docker host (running in an unprivileged LXC Container)
13+
5. A "fake" SMTP / IMAP Server
14+
15+
The environment has everything you need to run the domain, including TLS certificates and e-Mail (internal only)
16+
17+
### Why?
18+
19+
A lot of examples and samples in the internet use the "example.com" domain. Testing software and running it in a "production" environment, i.e. in your "real" network can be cumbersome, because:
20+
21+
- you might break something
22+
- you jeopardize the security and/or reliability of your network
23+
- you would have to change things and roll them back later
24+
- in order to make the examples run in the network, you need to change a lot of config files
25+
26+
For all these reasons, a test environment or "Sandbox" can be extremely useful.
27+
28+
- apply samples as they are without too many changes (we run the example.com domain - you remember ;-) )
29+
- No influence on the "real" world - everything is safely encapsulated
30+
- Quick deployment of Containers or VMs into the environment - just give a machine the virtual bridge as network and it will run inside the sandbox
31+
- The client container is lightweight, RDP makes access from Linux or Windows easy
32+
33+
### How? (1) - Preparation steps
34+
35+
Create a virtual network for your test "sandbox" that is connected nowhere (i.e. will only be visible inside the example.com). This will be the network that your example.com domain will use.
36+
37+
- Select the PVE Server in the Proxmox VE GUI
38+
- Select the "Network" node
39+
- Click on "Create" - "Linux Bridge"
40+
- do only fill out the following fields (i.e. leave all others blank):
41+
- Name (e.g. "vmbr999")
42+
- Autostart: ticked
43+
- VLAN aware: ticked
44+
- Comment (e.g. "Virtual Sandbox Bridge")
45+
46+
### How? (2) - Installation
47+
48+
The installation can be done automatically.
49+
Run the following command (as root) on the PVE Server:
50+
51+
### More Info
52+
53+

config

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# ###################################
2+
# general config for the
3+
# example.com Sandbox
4+
# ###################################
5+
6+
# the "virtual WAN" - this is the network
7+
# going to the internet, i.e. your "normal"
8+
# Proxmox Network, by default it's vmbr0
9+
10+
WAN=vmbr0
11+
12+
# the "virtual LAN" - this is the network
13+
# that your example.com domain will run in,
14+
# i.e. the "encapsulated" network
15+
# that you created as a preparation step
16+
17+
LAN=vmbr111
18+
19+
# The domain that you want to have inside
20+
# your virtual world
21+
22+
DOMAIN=example.com
23+
24+
# The storage where your containers shall reside
25+
# e.g. local or local-lvm or local-disc etc.
26+
27+
STORAGE=local-lvm
28+
29+
# CTTEMPLATE is the name of the template to use
30+
31+
TEMPLATENAME=debian-11-standard_11.6-1_amd64.tar.zst
32+
TEMPLATESTORAGE=local
33+
34+
# CTID contains a list of Container/VM IDs to use
35+
36+
CTID=701,702,703
37+
38+
# OPENWRTURL contains the URL for the OpenWrt Image to use.
39+
40+
OPENWRTURL="https://downloads.openwrt.org/releases/22.03.3/targets/x86/64/openwrt-22.03.3-x86-64-generic-ext4-combined.img.gz"
41+
42+
# the ROUTERIP is used later by the client Script in order to connect to the
43+
# router and do the necessary changes. Change it here if needed.
44+
# Furthermore, after the first installation step (when the script halts in order to
45+
# let you check the router's internet connection), log into the router shell
46+
# from the Proxmox GUI and run
47+
# uci set network.lan.ipaddr='x.x.x.x' ; uci commit ; reboot
48+
49+
ROUTERIP=192.168.1.1

deploy-sandbox.sh

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
#!/bin/bash
2+
3+
# ############################################
4+
# This is the main deploy script
5+
# that creates all the containers for the
6+
# example.com domain
7+
# ############################################
8+
9+
# include the config file
10+
. config
11+
12+
# The script needs to be run as root!
13+
# if we are not root, we will exit
14+
if [ "$EUID" -ne 0 ]
15+
then echo "Please run as root"
16+
exit
17+
fi
18+
19+
# ask for consent and abort or start the installation
20+
(cat) <<EOF
21+
This will install a virtual network
22+
on your Proxmox VE host.
23+
the parameters that you have chosen are:
24+
25+
Domain name: $DOMAIN
26+
Virtual LAN interface: $LAN
27+
Virtual WAN interface: $WAN
28+
Container Storage: $STORAGE
29+
30+
Please type Enter to continue or CTRL-C to abort
31+
EOF
32+
read
33+
34+
echo "Please specify a root password for the containers (input not shown)"
35+
read -s ROOTPASSWD
36+
echo "Please specify a non-root user name for the client container"
37+
read NONROOTUSER
38+
echo "Please specify a password for the non-root user (input not shown)"
39+
read -s NONROOTPASSWD
40+
41+
42+
# #########################################
43+
echo "##### finding the template"
44+
# #########################################
45+
46+
pveam download $TEMPLATESTORAGE $TEMPLATENAME
47+
CTTEMPLATE=$(pveam list $TEMPLATESTORAGE |grep $TEMPLATENAME | cut -d " " -f 1 -)
48+
if [ "X" == "X${CTTEMPLATE}" ]; then
49+
echo "Template not available - exiting"
50+
exit
51+
fi
52+
53+
# #########################################
54+
echo "##### deploying the router"
55+
# #########################################
56+
57+
OPENWRTID=$(echo $CTID | cut -d "," -f 3 -)
58+
qm create $OPENWRTID --cores 1 --name "exc-OpenWrt" --net0 model=virtio,bridge=$LAN --net1 model=virtio,bridge=$WAN --storage $STORAGE --memory 512
59+
wget -q -O - $OPENWRTURL | gunzip -c >/tmp/openwrt.img
60+
qm importdisk $OPENWRTID /tmp/openwrt.img $STORAGE --format qcow2
61+
qm set $OPENWRTID --ide0 $STORAGE:vm-$OPENWRTID-disk-0
62+
qm set $OPENWRTID --boot order=ide0
63+
rm /tmp/openwrt.img
64+
qm start $OPENWRTID
65+
66+
echo -e "\n ######### Please make sure the router has internet access"
67+
echo -e " ######### (open a shell on the VM and ping www.google.com or the like)"
68+
echo -e "\n ######### press ENTER to continue\n"
69+
read
70+
71+
# #########################################
72+
echo "##### deploying the client"
73+
# #########################################
74+
75+
CLIENTID=$(echo $CTID | cut -d "," -f 1 -)
76+
pct create $CLIENTID $CTTEMPLATE \
77+
--cores 1 \
78+
--description "RDP Server for the ${DOMAIN} domain" \
79+
--hostname "exc-Client" \
80+
--memory 2048 \
81+
--password "$ROOTPASSWD" \
82+
--storage $STORAGE \
83+
--net0 name=eth0,bridge=$WAN,ip=dhcp \
84+
--net1 name=eth1,bridge=$LAN,ip=dhcp \
85+
--features nesting=1 \
86+
--unprivileged 1
87+
88+
# #########################################
89+
echo "##### deploying the docker-host"
90+
# #########################################
91+
92+
DOCKERID=$(echo $CTID | cut -d "," -f 2 -)
93+
pct create $DOCKERID $CTTEMPLATE \
94+
--cores 1 \
95+
--description "Docker host for the ${DOMAIN} domain" \
96+
--hostname "exc-Docker" \
97+
--memory 2048 \
98+
--password "$ROOTPASSWD" \
99+
--storage $STORAGE \
100+
--net0 name=eth1,bridge=$LAN,ip=dhcp \
101+
--features keyctl=1,nesting=1 \
102+
--unprivileged 1
103+
104+
echo -e "\n ######### Please check the settings of the containers in the Proxmox GUI \n ######### press ENTER to continue\n"
105+
read
106+
107+
108+
# #########################################
109+
echo "##### starting the containers"
110+
# #########################################
111+
112+
# start the containers
113+
pct start $CLIENTID
114+
pct start $DOCKERID
115+
116+
# #########################################
117+
echo -e "\n ##### creating self-signed certs \n"
118+
# #########################################
119+
120+
# in case the domain is not called example.com, let's bluntly replace it in the config file
121+
sed -i s/example.com/${DOMAIN}/ imap.cnf
122+
sed -i s/example.com/${DOMAIN}/ wildcard.cnf
123+
124+
# create the Certificates - first the CA
125+
openssl req -newkey rsa:2048 -keyout rootCA.key -x509 -days 3650 -nodes -out rootCA.crt -subj "/CN=AAA_TestCA/C=DE/O=AAA_onemarcfifty/emailAddress=admin@${DOMAIN}"
126+
127+
# now the CSR and cert for the *.example.com wildcard
128+
openssl req -newkey rsa:2048 -nodes -keyout wildcard.key -out wildcard.csr -subj "/CN=*.${DOMAIN}/C=DE/O=AAA_onemarcfifty/emailAddress=admin@${DOMAIN}"
129+
openssl x509 -req -in wildcard.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out wildcard.crt -days 3650 -sha256 -extfile wildcard.cnf -extensions req_ext
130+
cat wildcard.crt rootCA.crt >wildcard_fullchain.crt
131+
132+
# now the CSR and cert for the imap server
133+
openssl req -newkey rsa:2048 -nodes -keyout imap.key -out imap.csr -subj "/CN=imap.${DOMAIN}/C=DE/O=AAA_onemarcfifty/emailAddress=admin@${DOMAIN}"
134+
openssl x509 -req -in imap.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out imap.crt -days 3650 -sha256 -extfile imap.cnf -extensions req_ext
135+
cat imap.crt rootCA.crt >imap_fullchain.crt
136+
137+
# copy the certificates over to the containers
138+
for THECONTAINER in $CLIENTID $DOCKERID ; do
139+
pct exec $THECONTAINER -- mkdir -p /etc/certificates/${DOMAIN}
140+
for i in *.crt *.key ; do
141+
pct push $THECONTAINER $i /etc/certificates/${DOMAIN}/${i}
142+
done
143+
done
144+
145+
# #########################################
146+
echo -e "\n ##### configuring the containers \n"
147+
# #########################################
148+
149+
# create a non-root user
150+
pct exec $CLIENTID -- useradd -m -s /bin/bash -G sudo $NONROOTUSER
151+
pct exec $CLIENTID -- bash -c "echo -e '$NONROOTPASSWD\n$NONROOTPASSWD\n' | passwd $NONROOTUSER"
152+
153+
# push dhcp settings to avoid routing over the ingress interface
154+
pct push $CLIENTID exc-client/dhclient.conf /etc/dhcp/dhclient.conf
155+
pct exec $CLIENTID -- systemctl restart networking
156+
157+
# push and execute the init script to the client
158+
pct push $CLIENTID exc-client/init-router-script.sh /root/init-router-script.sh
159+
pct push $CLIENTID exc-client/init-script.sh /root/init-script.sh
160+
pct exec $CLIENTID -- bash /root/init-script.sh "$NONROOTUSER" "$DOMAIN" "$ROUTERIP"
161+
162+
# push and execute the init script to the docker host
163+
pct push $DOCKERID exc-docker/init-script.sh /root/init-script.sh
164+
pct exec $DOCKERID -- bash /root/init-script.sh "$NONROOTUSER" "$DOMAIN"
165+
166+
echo -e "\n ############# DONE - Please reboot all VMs and CTs \n"
167+
echo -e "\n ############# and then connect with RDP to the following IP address : \n"
168+
pct exec $CLIENTID -- ip -br addr | grep eth0

destroy-sandbox.sh

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/bin/bash
2+
3+
# ############################################
4+
# This destroys all Containers and VMs
5+
# of the example.com domain
6+
# ############################################
7+
8+
# include the config file
9+
10+
. config
11+
12+
# The script needs to be run as root!
13+
# if we are not root, we will exit
14+
15+
if [ "$EUID" -ne 0 ]
16+
then echo "Please run as root"
17+
exit
18+
fi
19+
20+
(cat) <<EOF
21+
This will destroy all containers
22+
and VMs of the $DOMAIN domain!!!
23+
24+
Please type Enter to continue or CTRL-C to abort
25+
EOF
26+
read
27+
28+
OPENWRTID=$(echo $CTID | cut -d "," -f 3 -)
29+
qm stop $OPENWRTID
30+
qm destroy $OPENWRTID
31+
32+
CLIENTID=$(echo $CTID | cut -d "," -f 1 -)
33+
pct stop $CLIENTID
34+
pct destroy $CLIENTID
35+
36+
DOCKERID=$(echo $CTID | cut -d "," -f 2 -)
37+
pct stop $DOCKERID
38+
pct destroy $DOCKERID
39+
40+

exc-client/dhclient.conf

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Configuration file for /sbin/dhclient.
2+
#
3+
# This is a sample configuration file for dhclient. See dhclient.conf's
4+
# man page for more information about the syntax of this file
5+
# and a more comprehensive list of the parameters understood by
6+
# dhclient.
7+
#
8+
# Normally, if the DHCP server provides reasonable information and does
9+
# not leave anything out (like the domain name, for example), then
10+
# few changes must be made to this file, if any.
11+
#
12+
13+
option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;
14+
15+
send host-name = gethostname();
16+
17+
interface "eth0" {
18+
request subnet-mask, broadcast-address, time-offset,
19+
host-name,
20+
interface-mtu,
21+
ntp-servers;
22+
}
23+
24+
interface "eth1" {
25+
request subnet-mask, broadcast-address, time-offset, routers,
26+
domain-name, domain-name-servers, domain-search, host-name,
27+
dhcp6.name-servers, dhcp6.domain-search, dhcp6.fqdn, dhcp6.sntp-servers,
28+
netbios-name-servers, netbios-scope, interface-mtu,
29+
rfc3442-classless-static-routes, ntp-servers;
30+
}

exc-client/init-router-script.sh

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/bin/ash
2+
3+
# ################################
4+
# the init script for the router
5+
# ################################
6+
7+
DOMAIN=$1
8+
9+
# add the domain to the dnsmasq settings
10+
# and allow upstream RFC 1918 addresses
11+
uci set dhcp.@dnsmasq[0].domainneeded='0'
12+
uci set dhcp.@dnsmasq[0].rebind_protection='0'
13+
uci set dhcp.@dnsmasq[0].local="/${DOMAIN}/"
14+
uci set dhcp.@dnsmasq[0].domain="${DOMAIN}"
15+
uci set dhcp.@dnsmasq[0].boguspriv='0'
16+
uci commit
17+
18+
# add the mail relevant settings (Server CNAMEs and MX record)
19+
if grep imap /etc/dnsmasq.conf ; then
20+
echo "dnsmasq Config seems to be there already"
21+
else
22+
(cat >>/etc/dnsmasq.conf) <<EOF
23+
cname=imap,exc-Docker
24+
cname=smtp,exc-Docker
25+
cname=mail,exc-Docker
26+
cname=imap.${DOMAIN},exc-Docker
27+
cname=smtp.${DOMAIN},exc-Docker
28+
cname=mail.${DOMAIN},exc-Docker
29+
mx-host=${DOMAIN},mail.${DOMAIN},10
30+
EOF
31+
fi
32+
33+
# apply all changes
34+
/etc/init.d/dnsmasq restart

0 commit comments

Comments
 (0)