Skip to content

Proxy Mode for nexd

The normal mode of operation for nexd is to create a tunneled network interface on the device with an IP address within a Nexodus VPC. Creating this network interface requires elevated privileges, so it is not usable in all environments.

Containers are a common example of an environment where nexd cannot be run in its normal mode. In these cases, nexd can be run in proxy mode. In proxy mode, nexd will not create a tunneled network interface, but will instead operate as a layer 4 proxy.

Proxy Rules

Proxy rules must be specified as command line flags to nexd after specifying the proxy subcommand.

Beware of placement of flags to nexd

nexd has both general flags and subcommand-specific flags. When running nexd in proxy mode, the subcommand-specific flags must be specified after the subcommand. For example, here is an example of providing a general flag, as well as a proxy subcommand-specific flag:

nexd --request-ip 100.100.0.50 proxy --ingress $INGRESS_PROXY_RULE

Ingress Proxy

Ingress proxy rules are specified with the --ingress flag. This flag can be specified multiple times to specify multiple ingress proxy rules. This is the format for an ingress proxy rule:

--ingress protocol:port:destination_ip:destination_port
  • protocol - may be tcp or udp
  • port - the port on the host that the proxy will listen on for connections made from a network able to access this device.
  • destination_ip - the IP address of the destination within a Nexodus VPC that the proxy will forward traffic to.
  • destination_port - the port on the destination within a Nexodus VPC that the proxy will forward traffic to.

Here is an example showing an ingress proxy rule:

nexd proxy --ingress tcp:443:10.10.100.152:8443
flowchart TD
 linkStyle default interpolate basis
 device1[Remote device running nexd<br/><br/>IP: 100.100.0.1<br/><br/>Initiates connection to 100.100.0.2:443]-->|tunnel|network{Nexodus Network<br/><br/>100.64.0.0/10}
 network-->|tunnel|container[Container running nexd in proxy mode.<br/><br/>Nexodus IP: 100.100.0.2<br/>Local Network IP: 10.10.100.151<br/><br/>Accepts connections on 100.100.0.2:443 and forwards to 10.10.100.152:8443]

 subgraph Local Network - 10.10.100.0/24
 container-->|tcp|dest(Destination listening on port 8443<br/><br/>Local Network IP: 10.10.100.152)
 end

Egress Proxy

Egress proxy rules are specified with the --egress flag. This flag can be specified multiple times to specify multiple egress proxy rules. This is the format for an egress proxy rule:

--egress protocol:port:destination:destination_port
  • protocol - may be tcp or udp
  • port - the port that nexd will accept connections to made to its IP address within the Nexodus VPC this device is a member of.
  • destination - the IP address or hostname of the destination on a network accessible to the device that the proxy will forward traffic to.
  • destination_port - the port on the destination on a network accessible to the device that the proxy will forward traffic to.

Here is an example showing an egress proxy rule:

nexd proxy --egress tcp:443:100.100.0.1:8443
flowchart TD
 linkStyle default interpolate basis
 network{Nexodus Network<br/><br/>100.64.0.0/10}-->|tunnel|device1[Remote device running nexd <br/><br/>Nexodus IP: 100.100.0.1<br/><br/>Running a service that listens on TCP port 8443]
 container[Container running nexd in proxy mode.<br/><br/>Nexodus IP: 100.100.0.2<br/>Local Network IP: 10.10.100.151<br/><br/>Accepts connections on 10.10.100.151:443 and forwards to 100.100.0.1:8443]-->|tunnel|network

 subgraph Local Network - 10.10.100.0/24
 dest(Source application connecting to port 443 on 10.10.100.151<br/><br/>Local Network IP: 10.10.100.152)-->|tcp|container
 end

UDP Proxy Behavior

Since UDP is a connectionless protocol, nexd proxy must maintain its own state for each UDP flow to ensure that return traffic is forwarded appropriately. These flows time out after 60 seconds of inactivity.

Proxy Load Balancing

If multiple rules share the same protocol and listener port, then the proxy will use simple round-robin load balancing of connections across the destination hosts and ports.

Managing Rules with Nexctl

In addition to configuring rules as command line flags, nexctl can be used to dynamically add or remove proxy rules. Rules that are added dynamically are persisted across nexd proxy restarts.

To add a rule:

nexctl nexd proxy add --ingress tcp:443:10.0.10.34:8443

To remove a rule:

nexctl nexd proxy remove --ingress tcp:$43:10.0.10.34:8443

To list currently active rules:

nexctl nexd proxy list

Demo Using Containers

This section provides instructions on running an end-to-end demonstration of using nexd proxy on both ends of a connection. We will run two containers: one running an http server, and another that would like to reach that http server. nexd in each container will negotiate an encrypted tunnel directly between each other. The connection will go over this tunnel.

flowchart TD
 linkStyle default interpolate basis
 device1[Container running nexd proxy and curl<br/><br/>Nexodus IP: 100.100.0.1<br/><br/>Initiates connection to 100.100.0.2:80]-->|tunnel|network{Nexodus Network<br/><br/>100.64.0.0/10}
 network-->|tunnel|container[Container running nexd proxy and an http server.<br/><br/>Nexodus IP: 100.100.0.2<br/><br/>Accepts connections on 100.100.0.2:80 and forwards to 127.0.0.1:8080]

Container with a proxy and an HTTP server

First, start a container to act as the http server.

docker run -it --rm --name nexd-proxy-demo-server quay.io/nexodus/nexd

From within the container, start an http server and then start nexd proxy. Follow the authentication instructions in the output.

Note

Once the device has authenticated with the Nexodus control plane, watch the output to see what IP has been assigned to this proxy. The rest of this demo assumes it was 100.100.0.1.

echo "It works!" > index.html
python3 -m http.server 8080 &

./nexd --service-url https://try.nexodus.io proxy --ingress tcp:80:127.0.0.1:8080

Container with a proxy and an HTTP client

Next we need a second container that will act as the http client that will connect to a locally running nexd proxy to reach its destination. Start the container:

docker run -it --rm --name nexd-proxy-demo-client quay.io/nexodus/nexd

From within the second container, start nexd proxy in the background, and follow the authentication instructions in the output from nexd.

REMOTE_NEXD_IP=100.100.0.1
./nexd --service-url https://try.nexodus.io proxy --egress tcp:80:${REMOTE_NEXD_IP}:80 &

Once the device has succcessfully connected and authenticated with Nexodus, you should be able to reach the http server from the first container over a Nexodus managed tunnel.

$ curl http://localhost
It works!