The controller (server) is a set of containers that allow the admin to remotely manage multiple NethSecurity installations (firewalls).
Firewalls can register to the server using ns-plug client. Upon registration the server will:
- create a VPN configuration which is sent back to the firewall
- create a route inside the proxy to access the firewall Luci RPC
- store credentials to access the remote firewall
Depending on your needs, you can setup a development environment to test the controller locally or you can install it on a NethServer 8 machine.
This environment integrates only the basic componentes:
- VPN server
- API server
- proxy server
- UI server
It's suitable for development of the the basic controller features, but it does not include the full features like reporting and logging. You can use it also to develop the UI.
If you need a local development environment, you can use the dev.sh
script to start a podman pod with all the containers needed to run the controller.
First make sure to have podman installed on your server.
Containers should run under non-root users, but first you need to configure the tun device and the user.
As root, execute:
ip tuntap add dev tunsec mod tun
ip addr add 172.21.0.1/16 dev tunsec
ip link set dev tunsec up
If you're running the dev environment on a distro with SELinux enabled, you also may need to create a module to allow the controller to access the tun device. Just execute:
checkmodule -M -m -o controller.mod controller.te
semodule_package -o controller.pp -m controller.mod
semodule -i controller.pp
Then change to non-root user, clone this repository and execute:
su - controller
./dev.sh start
To stop the pod, execute:
./dev.sh stop
By default, the script will use images tagged with the current branch name.
If you want to use a specific image tag, you can set the IMAGE_TAG
environment
To run a specific image tag, you can use:
IMAGE_TAG=<tag> ./dev.sh start
The server will be available at http://localhost:8080/
.
Default credentials are: admin/admin
.
You can install the controller on NS8.
After the installation and first configuration of the controller, enable the debug mode to allow the UI to connect to the controller API:
runagent -m nethsecurity-controller1 sed -i 's/GIN_MODE=release/GIN_MODE=debug/' api.env
runagent -m nethsecurity-controller1 systemctl --user restart controller
Above commands assume that the controller instance is named nethsecurity-controller1
.
If you need to the develop the UI, first clone the nethsecurity-ui.
Then you can choose to connect to the local development environment or the NethServer 8 environment.
To connect to the local development environment, you need to:
- start the controller using the
dev.sh
script from thenethsecurity-controller
repository:IMAGE_TAG=pr-123 ./dev.sh start
- move to the
nethsecurity-ui
directory:git clone git@github.com:NethServer/nethsecurity-ui.git cd nethsecurity-ui
- inside the UI directory, setup the
.env.development
file to connect to the controller APIcat <<EOF > .env.development VITE_API_SCHEME=http VITE_CONTROLLER_API_HOST=localhost:8080 VITE_UI_MODE=controller EOF
- still inside the UI directory, start the UI in dev mode:
./dev.sh
- access to the dev UI URL generated by vite, usually
http://localhost:5173/
First, make sure the controller is running in debug mode, as described above.
To connect to the NethServer 8 environment, you need to:
- move to the
nethsecurity-ui
directory:git clone git@github.com:NethServer/nethsecurity-ui.git cd nethsecurity-ui
- inside the UI directory, setup the
.env.development
file to connect to the controller APIcat <<EOF > .env.development VITE_API_SCHEME=https VITE_CONTROLLER_API_HOST=controller.example.com VITE_UI_MODE=controller EOF
- still inside the UI directory, start the UI in dev mode:
./dev.sh
- access to the dev UI URL generated by vite, usually
http://localhost:5173/
It's possible to develop the API server without the need to run the full controller stack.
This environment is suitable to develop the API server and test it using the curl
command, but
does not integrate nor the VPN server nor the proxy server.
To start the API server in development mode:
- first, make sure that a Timescale DB is running and accessible:
podman run --rm --name timescaledb -p 5432:5432 -e POSTGRES_PASSWORD=password -e POSTGRES_USER=report timescale/timescaledb-ha:pg16
- then move to the
api
directory, create thedata
directory and build the API server:cd api mkdir -p data go build
- start the API server by setting up all required environment variables:
LISTEN_ADDRESS=0.0.0.0:5000 ADMIN_USERNAME=admin ADMIN_PASSWORD=admin SECRET_JWT=secret PROMTAIL_ADDRESS=127.0.0.1 PROMTAIL_PORT=6565 PROMETHEUS_PATH="/prometheus" WEBSSH_PATH="/webssh" GRAFANA_PATH="/grafana" REGISTRATION_TOKEN=1234 REPORT_DB_URI=postgres://report:password@127.0.0.1:5432/report GRAFANA_POSTGRES_PASSWORD=password ISSUER_2FA=test ENCRYPTION_KEY=12345678901234567890123456789012 VALID_SUBSCRIPTION=true CREDENTIALS_DIR=data DATA_DIR=data ./api
- the API server will be available at
http://localhost:5000/
To run the testing suite:
- first, make sure that a Timescale DB is running and accessible:
podman run --rm --name timescaledb -p 5432:5432 -e POSTGRES_PASSWORD=password -e POSTGRES_USER=report timescale/timescaledb-ha:pg16
- then move to the
api
directory and run the tests:cd api go test
General workflow:
- Access the controller and add a new machine using the
add
API below. This will generate a join code containing the FQDN of the controller, a registration token, and the unit UUID. - Connect the NethSecurity unit and register the machine using the join code.
- Return to the controller and manage the unit.
- The UI retrieves a token for the NethSecurity unit:
curl http://localhost:8080/api/servers/login/clientX
- THe UI Uses the token to invoke Luci APIs:
curl http://localhost:8080/clientX/cgi-bin/luci/rpc/...
The controller is composed by 4 services:
- nethsec-vpn: OpenVPN server, it authenticates the machines and create routes for the proxy, it listens on port 1194
- nethsec-proxy: traefik forwards requests to the connected machines using the machine name as path prefix, it listens on port 8181
- nethsec-api: REST API python server to manage nethsec-vpn clients, it listens on port 5000
- nethsec-ui: lighttpd instance serving static UI files, it listens on port 3000
The following environment variables can be used to configure the containers:
FQDN
: default is the container/pod hostnameOVPN_NETWORK
: OpenVPN network, default is172.21.0.0
OVPN_NETMASK
: OpenVPN netmask, default is255.255.0.0
OVPN_CN
: OpenVPN certificate CN, default isnethsec
OVPN_UDP_PORT
: OpenVPN UDP port, default is1194
OVPN_TUN
: OpenVPN tun device name, default istunsec
UI_PORT
: UI listening port, default is3000
UI_BIND_IP
: UI binding IP, default is0.0.0.0
API_PORT
: API server listening port, default is5000
API_BIND_IP
: API server listening IP, default is127.0.0.1
API_USER
: controller admin user, default isadmin
API_PASSWORD
: controller admin password, it must be passed as SHA56SUM, default isadmin
API_SECRET
: JWT secret tokenAPI_DEBUG
: enable debug logging and CORS if set to1
, default is0
API_SESSION_DURATION
: JWT session duration in seconds, default is 7 daysPROXY_PORT
: proxy listening port, default is8080
PROXY_BIND_IP
: proxy binding IP, default is0.0.0.0
REPORT_DB_URI
: Timescale DB URI, likepostgresql://user:password@host:port/dbname
ALLOWED_IPS
: comma-separated list of allowed IPs, if empty, all IPs are allowed, default is emptyPUBLIC_ENDPOINTS
: comma-separated list of public endpoints, that can be accessed even ifALLOWED_IPS
is set, default is empty If ALLOWED_IPS is set, the public endpoints should allow registration and ingestions from units, a good value should be:/api/ingest,/api/units/register
Manage server registrations using the REST API server. Request should be sent to the proxy server.
Almost all APIs are authenticated using JWT.
Authentication work-flow:
- send user name and password to
/login
API - retrieve authorization tokens:
access_token
: it's the token used to executed all APIs, it expires after an hourrefresh_token
: this token can be used only to call the/refresh
API and request a newaccess_token
, it expires afterAPI_SESSION_DURATION
seconds (default to 7 days)
- invoke other APIs by setting the header
Authorization: Bearer <access_token>"
Unauthenticated APIs:
/login
: execute the login and retrieve the tokens/register
: invoked by firewalls to register themselves, this API should be always invoked using a valid HTTPS endpoint to ensure the identity of the server
See the API documentation for more details.
Each container is built using a Containerfile, which is both compatible with docker build
command and podman build
.
To build the images using podman, you can use the following:
podman build --target dist --layers --force-rm --jobs 0 <directory>
Where <directory>
is the path to any of the directory to build.
Optionally, you can add the --tag <imagetag>
to tag the image with a specific name.