From b6b5c0c27634ff1e1396c02df91741b907dc2496 Mon Sep 17 00:00:00 2001 From: Michal Opala Date: Fri, 25 Oct 2024 12:02:36 +0200 Subject: [PATCH] F OpenNebula/one#6641: Add TProxy documentation (#3093) Co-authored-by: Pedro Ielpi --- source/images/tproxy-diagram.drawio.png | Bin 0 -> 71415 bytes source/images_drawio/tproxy-diagram.drawio | 164 ++++++++++++ .../opennebula_services/onegate.rst | 230 ++--------------- .../network_management/index.rst | 1 + .../network_management/tproxy.rst | 234 ++++++++++++++++++ 5 files changed, 418 insertions(+), 211 deletions(-) create mode 100644 source/images/tproxy-diagram.drawio.png create mode 100644 source/images_drawio/tproxy-diagram.drawio create mode 100644 source/management_and_operations/network_management/tproxy.rst diff --git a/source/images/tproxy-diagram.drawio.png b/source/images/tproxy-diagram.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..c7ee09c42a4cbb20830d87bb2cfd7783ea383d95 GIT binary patch literal 71415 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/installation_and_configuration/opennebula_services/onegate.rst b/source/installation_and_configuration/opennebula_services/onegate.rst index c7c97f0b20..d7b7773f42 100644 --- a/source/installation_and_configuration/opennebula_services/onegate.rst +++ b/source/installation_and_configuration/opennebula_services/onegate.rst @@ -123,229 +123,37 @@ Other logs are also available in Journald. Use the following command to show: .. |onegate_net| image:: /images/onegate_net.png -.. - Advanced Setup - ============== - - - Example: Use OneGate/Proxy to Improve Security - ---------------------------------------------- - - In addition to the OneGate itself, OpenNebula provides transparent TCP-proxy for the OneGate's network traffic. - It's been designed to drop the requirement for guest VMs to be directly connecting to the service. Up to this point, - in cloud environments like :ref:`OneProvision/AWS `, the OneGate service had to be exposed - on a public IP address. Please take a look at the example diagram below: - - .. graphviz:: - - digraph { - graph [splines=true rankdir=LR ranksep=0.7 bgcolor=transparent]; - edge [dir=both color=blue arrowsize=0.6]; - node [shape=plaintext fontsize="11em"]; - - { rank=same; - F1 [label=< - - -
- -
ONE / 1 (follower)
eth1: 192.168.150.1
- >]; - F2 [label=< - - -
- -
- -
ONE / 2 (leader)
opennebula-gate
192.168.150.86:5030
eth1:
192.168.150.2
192.168.150.86 (VIP)
- >]; - F3 [label=< - - -
- -
ONE / 3 (follower)
eth1: 192.168.150.3
- >]; - } - - { rank=same; - H1 [label=< - - -
- -
- -
- -
- -
ONE-Host / 1
opennebula-gate-proxy
169.254.16.9:5030
lo:
127.0.0.1
169.254.16.9
⇅ (forwarding)
br0: 192.168.150.4
- >]; - H2 [label=< - - -
- -
- -
- -
- -
ONE-Host / 2
opennebula-gate-proxy
169.254.16.9:5030
lo:
127.0.0.1
169.254.16.9
⇅ (forwarding)
br0: 192.168.150.5
- >]; - } - - { rank=same; - G1 [label=< - - -
- -
- -
- -
VM-Guest / 1
ONEGATE_ENDPOINT=
http://169.254.16.9:5030
static route:
169.254.16.9/32 dev eth0
eth0: 192.168.150.100
- >]; - G2 [label=< - - -
- -
- -
- -
VM-Guest / 2
ONEGATE_ENDPOINT=
http://169.254.16.9:5030
static route:
169.254.16.9/32 dev eth0
eth0: 192.168.150.101
- >]; - } - - F1:s -> F2:n [style=dotted arrowhead=none]; - F2:s -> F3:n [style=dotted arrowhead=none]; - - F2:eth1:e -> H1:br0:w; - F2:eth1:e -> H2:br0:w; - - H1:br0:e -> G1:eth0:w; - H2:br0:e -> G2:eth0:w; - } - - | - - In this altered OneGate architecture, each hypervisor Node runs a process, which listens for connections on a dedicated - `IPv4 Link-Local Address `_. - After a guest VM connects to the proxy, the proxy connects back to OneGate and transparently forwards all the protocol traffic - both ways. Because a guest VM no longer needs to be connecting directly, it's now easy to setup a VPN/TLS tunnel between - hypervisor Nodes and the OpenNebula Front-end machines. It should allow for OneGate communication to be conveyed through securely, - and without the need for exposing OneGate on a public IP address. - - Each of the OpenNebula DEB/RPM node packages: ``opennebula-node-kvm`` and ``opennebula-node-lxc`` contains the ``opennebula-gate-proxy`` systemd service. To enable and start it on your Hosts, execute as **root**: - - .. prompt:: bash # auto - - # systemctl enable opennebula-gate-proxy.service --now - - You should be able to verify, that the proxy is running with the default config: - - .. prompt:: bash # auto +Advanced Setup +============== - # ss -tlnp | grep :5030 - LISTEN 0 4096 169.254.16.9:5030 0.0.0.0:* users:(("ruby",pid=9422,fd=8)) +Example: Use Transparent OneGate Proxy to Improve Security +---------------------------------------------------------- - .. important:: +Add the following config snippet to the ``~oneadmin/remotes/etc/vnm/OpenNebulaNetwork.conf`` file on Front-end machines: - The ``:onegate_addr`` attribute is configured automatically in the ``/var/tmp/one/etc/onegate-proxy.conf`` file during - the ``onehost sync -f`` operation. That allows for an easy reconfiguration in the case of a larger (many Hosts) - OpenNebula environment. - - To change the value of the ``:onegate_addr`` attribute, edit the ``/var/lib/one/remotes/etc/onegate-proxy.conf`` - file and then execute the ``onehost sync -f`` operation as **oneadmin**: - - .. prompt:: bash $ auto - - $ gawk -i inplace -f- /var/lib/one/remotes/etc/onegate-proxy.conf <<'EOF' - BEGIN { update = ":onegate_addr: '192.168.150.86'" } - /^#*:onegate_addr:/ { $0 = update; found=1 } - { print } - END { if (!found) print update >>FILENAME } - EOF - $ onehost sync -f - ... - All hosts updated successfully. - - .. note:: - - As a consequence of the ``onehost sync -f`` operation, the proxy service will be automatically restarted - and reconfigured on every hypervisor Node. - - To change the value of the ``ONEGATE_ENDPOINT`` context attribute for each guest VM, edit the ``/etc/one/oned.conf`` file - on your Front-end machines. For the purpose of using the proxy, just specify an IP address from the ``169.254.0.0/16`` - subnet (by default it's ``169.254.16.9``) and then restart the ``opennebula`` service: - - .. prompt:: bash # auto - - # gawk -i inplace -f- /etc/one/oned.conf <<'EOF' - BEGIN { update = "ONEGATE_ENDPOINT = \"http://169.254.16.9:5030\"" } - /^#*ONEGATE_ENDPOINT[^=]*=/ { $0 = update; found=1 } - { print } - END { if (!found) print update >>FILENAME } - EOF - # systemctl restart opennebula.service - - And, last but not least, it's required from guest VMs to setup this static route: +.. code:: - .. prompt:: bash # auto + :tproxy: + # OneGate service. + - :service_port: 5030 + :remote_addr: 10.11.12.13 # OpenNebula Front-end VIP + :remote_port: 5030 - # ip route replace 169.254.16.9/32 dev eth0 +Propagate config to Hypervisor hosts, execute as ``oneadmin`` on the leader Front-end machine: - Perhaps one of the easiest ways to achieve it, is to alter a VM template by adding a :ref:`start script `: +.. code:: - .. prompt:: bash # auto + $ onehost sync -f - # (export EDITOR="gawk -i inplace '$(cat)'" && onetemplate update alpine) <<'EOF' - BEGIN { update = "START_SCRIPT=\"ip route replace 169.254.16.9/32 dev eth0\"" } - /^CONTEXT[^=]*=/ { $0 = "CONTEXT=[" update "," } - { print } - EOF - # onetemplate instantiate alpine - VM ID: 0 +Deploy a guest Virtual Machine and test OneGate connectivity from within: - Finally, by examining the newly created guest VM, you can confirm if OneGate is reachable: +.. code:: - .. prompt:: bash # auto + $ onegate vm show - # grep -e ONEGATE_ENDPOINT -e START_SCRIPT /var/run/one-context/one_env - export ONEGATE_ENDPOINT="http://169.254.16.9:5030" - export START_SCRIPT="ip route replace 169.254.16.9/32 dev eth0" - # ip route show to 169.254.16.9 - 169.254.16.9 dev eth0 scope link - # onegate vm show --json - { - "VM": { - "NAME": "alpine-0", - "ID": "0", - "STATE": "3", - "LCM_STATE": "3", - "USER_TEMPLATE": { - "ARCH": "x86_64" - }, - "TEMPLATE": { - "NIC": [ - { - "IP": "192.168.150.100", - "MAC": "02:00:c0:a8:96:64", - "NAME": "NIC0", - "NETWORK": "public" - } - ], - "NIC_ALIAS": [] - } - } - } +Read more in :ref:`Transparent Proxies `. +.. Example: Deployment Behind TLS Proxy ------------------------------------ diff --git a/source/management_and_operations/network_management/index.rst b/source/management_and_operations/network_management/index.rst index 3f5657b26b..f495579d3d 100644 --- a/source/management_and_operations/network_management/index.rst +++ b/source/management_and_operations/network_management/index.rst @@ -13,3 +13,4 @@ Virtual Network Management Security Groups Self Provision Virtual Routers + Transparent Proxies diff --git a/source/management_and_operations/network_management/tproxy.rst b/source/management_and_operations/network_management/tproxy.rst new file mode 100644 index 0000000000..7c29402d1d --- /dev/null +++ b/source/management_and_operations/network_management/tproxy.rst @@ -0,0 +1,234 @@ +.. _tproxy: + +================================================================================ +Transparent Proxies +================================================================================ + +Transparent Proxies make it possible to connect to management services, such as OneGate, by implicitly using the existing data center backbone networking. The OneGate service usually runs on the leader Front-end machine, which makes it difficult for Virtual Machines running in isolated virtual networks to contact it. This situation forces OpenNebula users to design virtual networking in advance, to ensure that VMs can securely reach OneGate. Transparent Proxies have been designed to remove that requirement. + +About the Design +================================================================================ + +|tproxy_diagram| + +Virtual networking in OpenNebula is bridge-based. Each Hypervisor that runs Virtual Machines in a specific Virtual Network pre-creates such a bridge before deploying the VMs. Transparent Proxies extend that design by introducing a pair of VETH devices, where one of two "ends" is inserted into the bridge and the other is boxed inside the dedicated network namespace. This makes it possible to deploy proxy processes that can be reached by Virtual Machine guests via TCP/IP securely, i.e. without compromising the internal networking of Hypervisor hosts. Proxy processes themselves form a "mesh" of daemons interconnected with UNIX sockets, which allows for complete isolation of the two involved TCP/IP stacks; we call this environment the "String-Phone Proxy." The final part of the solution requires that Virtual Machine guests contact services over proxy via the ``169.254.16.9`` link-local address on specific ports, instead of their real endpoints. + +Hypervisor Configuration +================================================================================ + +Transparent Proxies read their config from the ``~oneadmin/remotes/etc/vnm/OpenNebulaNetwork.conf`` file on the Front-end machines. The file uses the following syntax: + +.. code:: + + :tproxy_debug_level: 2 # 0 = ERROR, 1 = WARNING, 2 = INFO, 3 = DEBUG + :tproxy: + # OneGate service. + - :service_port: 5030 + :remote_addr: 10.11.12.13 # OpenNebula Front-end VIP + :remote_port: 5030 + # Custom service. + - :service_port: 1234 + :remote_addr: 10.11.12.34 + :remote_port: 1234 + :networks: [vnet_name_or_id] + +.. note:: + + The YAML snippet above defines two distinct proxies, where the first is the usual OneGate proxy and the second is a completely custom service. + +.. important:: + + If the ``:networks:`` YAML key is missing or empty, the particular proxy will be applied to *all* available Virtual Networks. Defining multiple entries with the identical ``:service_port:`` values will have no effect as the subsequent duplicates will be ignored by networking drivers. + +**To apply the configuration, you need to perform two steps:** + +1. On the leader Front-end machine: as the ``oneadmin`` system user, sync the ``OpenNebulaNetwork.conf`` file with the Hypervisor hosts, by running ``onehost sync -f``. +2. Power-cycle any running guests (for example by running ``onevm poweroff`` followed by ``onevm resume``); otherwise the desired configuration changes may show no effect. + +Guest Configuration +================================================================================ + +The most common use case of Transparent Proxies is for communication with OneGate. Below is an example Virtual Machine template: + +.. code:: + + NAME = "example0" + CONTEXT = [ + NETWORK = "YES", + SSH_PUBLIC_KEY = "$USER[SSH_PUBLIC_KEY]", + TOKEN = "YES" ] + CPU = "1" + DISK = [ + IMAGE = "img0" ] + GRAPHICS = [ + LISTEN = "0.0.0.0", + TYPE = "VNC" ] + MEMORY = "256" + NIC = [ + NETWORK = "vnet0", + NETWORK_UNAME = "oneadmin", + SECURITY_GROUPS = "100" ] + NIC_DEFAULT = [ + MODEL = "virtio" ] + OS = [ + ARCH = "x86_64" ] + +In the simplest (but still instructive) case, a Virtual Machine needs the following settings to connect to OneGate using Transparent Proxies: + +.. code:: + + $ grep ONEGATE_ENDPOINT /run/one-context/one_env + export ONEGATE_ENDPOINT="http://169.254.16.9:5030" + + $ ip route show to 169.254.16.9 + 169.254.16.9 dev eth0 scope link + +.. code:: + + $ onegate vm show -j | jq -r '.VM.NAME' + example0-0 + +Debugging +================================================================================ + +You can find driver logs for each guest on the Front-end machines, in ``/var/log/one/*.log``. + +Proxy logs are found on Hypervisor hosts, in ``/var/log/``. For example: + +.. code:: + + $ ls -1 /var/log/one_tproxy*.log + /var/log/one_tproxy.log + /var/log/one_tproxy_br0.log + +The internal implementation of Transparent Proxies involves several networking primitives combined together: + +* ``nft`` (``nftables``) to store the service mapping and manage ARP resolutions +* ``ip netns`` / ``nsenter`` family of commands to manage and use network namespaces +* ``ip link`` / ``ip address`` / ``ip route`` commands +* ``/var/tmp/one/vnm/tproxy`` the actual implementation of the "String-Phone" daemon mesh + +Below are several example command invocations, to gain familiarity with the environment. + +**Listing service mappings in nftables:** + +.. code:: + + $ nft list ruleset + ... + table ip one_tproxy { + map ep_br0 { + type inet_service : ipv4_addr . inet_service + elements = { 1234 : 10.11.12.34 . 1234, 5030 : 10.11.12.13 . 5030 } + } + } + +.. note:: + + The ``nftables`` config is not persisted across Hypervisor host reboots, as it is the default behavior in OpenNebula in general. + +**Listing all custom network namespaces:** + +.. code:: + + $ ip netns list + one_tproxy_br0 (id: 0) + +.. note:: + + Each active Virtual Network requires one of those namespaces to run the proxy inside. + +**Checking if the "internal" end of the VETH device pair has been put inside the dedicated namespace:** + +.. code:: + + $ ip netns exec one_tproxy_br0 ip address + 1: lo: mtu 65536 qdisc noop state DOWN group default qlen 1000 + link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 + 7: br0a@if8: mtu 1500 qdisc noqueue state UP group default qlen 1000 + link/ether 12:00:83:53:f4:3d brd ff:ff:ff:ff:ff:ff link-netnsid 0 + inet 169.254.16.9/32 scope global br0a + valid_lft forever preferred_lft forever + inet6 fe80::1000:83ff:fe53:f43d/64 scope link + valid_lft forever preferred_lft forever + +.. note:: + + In case multiple Hypervisor hosts participate in the Virtual Network's traffic, the ``169.254.16.9`` address stays the same regardless, the closest Hypervisor host is supposed to answer guest requests. + +**Checking if the default route for sending packets back into the bridge has been configured:** + +.. code:: + + $ ip netns exec one_tproxy_br0 ip route + default dev br0a scope link + +**Listing PIDs of running proxy processes:** + +.. code:: + + $ /var/tmp/one/vnm/tproxy status + one_tproxy: 16803 + one_tproxy_br0: 16809 + +.. note:: + + There is only a single ``one_tproxy`` process running in the default network namespace, it connects to real remote services. + +.. note:: + + There are multiple ``one_tproxy_*`` processes, they are boxed inside corresponding dedicated network namespaces and connect to the ``one_tproxy`` process using UNIX sockets. + +.. note:: + + There is no PID file management implemented. For simplicity, all proxy processes may be found by looking at the ``/proc/PID/cmdline`` process attributes. + +**Restarting/reloading config of proxy daemons:** + +.. code:: + + $ /var/tmp/one/vnm/tproxy restart + $ /var/tmp/one/vnm/tproxy reload + +.. important:: + + While you can manually run the ``start``, ``stop``, ``restart`` and ``reload`` commands as part of a debugging process, under normal circumstances the proxy daemons are completely managed by networking drivers. The command-line interface here is very minimal and does not require any extra parameters, as all the relevant config is stored in ``nftables``. + +Security Groups +================================================================================ + +Transparent Proxies can be used together with OpenNebula Security Groups. Below is an example of a security group template: + +.. code:: + + NAME = "example0" + + RULE = [ + PROTOCOL = "ICMP", + RULE_TYPE = "inbound" ] + RULE = [ + PROTOCOL = "ICMP", + RULE_TYPE = "outbound" ] + + RULE = [ + PROTOCOL = "TCP", + RANGE = "22", + RULE_TYPE = "inbound" ] + RULE = [ + PROTOCOL = "TCP", + RANGE = "80,443", + RULE_TYPE = "outbound" ] + + # Required for Transparent Proxies + RULE = [ + PROTOCOL = "TCP", + RANGE = "1234,5030", + RULE_TYPE = "outbound" ] + + # DNS + RULE = [ + PROTOCOL = "UDP", + RANGE = "53", + RULE_TYPE = "outbound" ] + +.. |tproxy_diagram| image:: /images/tproxy-diagram.drawio.png