bolkedebruin / rdpgw

Remote Desktop Gateway in Go for deploying on Linux/BSD/Kubernetes
Apache License 2.0
693 stars 117 forks source link

Is there any quickstart or step by step guide available? #97

Open georgygoshin opened 5 months ago

georgygoshin commented 5 months ago

Hello

Trying to start the gateway, spent a lot of time but still can't understand. I see by other user's questions / comments that it's working but can't find the way to do the same. Is there any quick-start guide for dockerhub version? Tried to grab it with portainer without any luck, now with simple docker on linux, ends with

Cannot get oidc provider: Get "http://keycloak:8080/auth/realms/rdpgw/.well-known/openid-configuration": dial tcp: lookup keycloak on

is there a way to quickly start without 2FA to connect from outside to Windows RDP in LAN ?

georgygoshin commented 5 months ago

I've made new keycloak installation, added realm and client, got the client ID and secret, need some walk thru all options

docker --run name rdpgw bolkedebruin/rdpgw:latest \ -e RDPGW_SERVERSSL_CERT_FILE=/etc/rdpgw/cert.pem < -- replaced with LE cert path -e RDPGW_SERVER__SSL_KEY_FILE=/etc/rdpgw.cert.pem < -- replaced with LE key path -e RDPGW_SERVERGATEWAY_ADDRESS=https://localhost:443 <-- replaced with real address -e RDPGW_SERVERSESSION_KEY=thisisasessionkeyreplacethisjetz # 32 characters <--- replaced with generated string -e RDPGW_SERVERSESSION_ENCRYPTION_KEY=thisisasessionkeyreplacethisnunu # 32 characters <--- replaced with generated string -e RDPGW_OPENIDPROVIDER_URL=http://keycloak:8080/auth/realms/rdpgw <-- replaced with real keycloak address -e RDPGW_OPENIDCLIENT_ID=rdpgw <-- replaced with client ID from Keycloak -e RDPGW_OPENIDCLIENT_SECRET=01cd304c-6f43-4480-9479-618eb6fd578f <-- replaced with client secret from Keycloak -e RDPGW_SECURITYSECURITY_PAA_TOKEN_SIGNING_KEY=prettypleasereplacemeinproductio # <--- replaced with generated string -v conf:/etc/rdpgw

First of all please comment, did I understood correctly these environment variables?

and after composing the command line with real valiues, docker --run name rdpgw bolkedebruin/rdpgw:latest responsed with the error

unknown flag: --run

docker run bolkedebruin/rdpgw:latest repsponded with error

unknown flag `e'

pbvdven commented 4 months ago

I just use it for home use i dont know about keycloak i use authentik thats installed on other machine

download the dev folder in this project. change the docker compose remove keycloak and xrdp part completely where it says rdpgw: remove depends on: keycloak and change or remove healthcheck

create for your gateway a provider "openid" and application in authentik.

then change the yaml inside the dev folder gatewayadres: your gateway adres that you made in ngnix or cloudflare for this purpose Host: change to your windows RDP ip port ProviderUrl: use the provided url in authentik when you created the provider and application url called OpenID Configuration Issuer ClientId: from authentik where your provider is ClientSecret: same place callback url redirect url you need to put in authentik at provider settings its the https url you created for this gateway and /callback

then you now can docker-compose build docker-compose up

then you should now get a rdp file if you go to /connect

there are some other options but this is the basic working you could also use a template rdp file to add some extra options like usb camera passtrough just copy from the original rdp. place the file default,rdp also in the dev folder and add default: default.rdp in yaml config.

you could also use multiple hosts but i didnt get that working i just deploy the gateway twice.

most info in this project you can find searching the issue pull requests and comments here and there.

Mikle-Bond commented 4 months ago

@georgygoshin

docker --run name rdpgw bolkedebruin/rdpgw:latest

First, it is docker run --name rdpgw, then all the options for container, and lastly it it the container name bolkedebruin/rdpgw:latest

As for the options, there's an undocumented quirk about environment variables. Where you set options about OpenId, you should use RDPGW_OPEN_ID__ instead of RDPGW_OPENID__ as a prefix.

disclaimer: no guaranty that the following command will work for you as presented, further adjustments will be needed.

docker run --name rdpgw `
` -e RDPGW_SERVER__SSL_CERT_FILE=/etc/rdpgw/cert.pem ` # < -- replaced with LE cert path
` -e RDPGW_SERVER__SSL_KEY_FILE=/etc/rdpgw/cert.key `  # < -- replaced with LE key path
` -e RDPGW_SERVER__GATEWAY_ADDRESS=https://externally-reachable-name:443 ` # <-- replaced with real address
` -e RDPGW_SERVER__SESSION_KEY=thisisasessionkeyreplacethisjetz ` # 32 characters <--- replaced with generated string
` -e RDPGW_SERVER__SESSION_ENCRYPTION_KEY=thisisasessionkeyreplacethisnunu ` # 32 characters <--- replaced with generated string
` -e RDPGW_OPEN_ID__PROVIDER_URL=http://localhost:8080/auth/realms/rdpgw ` # <-- replaced with real keycloak address
` -e RDPGW_OPEN_ID__CLIENT_ID=rdpgw ` # <-- replaced with client ID from Keycloak
` -e RDPGW_OPEN_ID__CLIENT_SECRET=01cd304c-6f43-4480-9479-618eb6fd578f ` # <-- replaced with client secret from Keycloak
` -e RDPGW_SECURITY__SECURITY_PAA_TOKEN_SIGNING_KEY=prettypleasereplacemeinproductio ` # <--- replaced with generated string
` -v conf:/etc/rdpgw `
` --network host `
` bolkedebruin/rdpgw:latest

Note, that RDPGW_OPEN_ID__PROVIDER_URL=http://keycloak:8080/auth/realms/rdpgw from your attempt tried to contact host, named keycloak, which is not available to docker container. You mention that you've made a local installation, and in the example I took the liberty to assume it is now reachable via http://localhost:8080/auth. To make it available to container, I've added --network host, which is not great for production anvironment, but might help you get started.

Another note: the command above uses conf volume. You should create it manually with docker volume create conf and populate it with certificate cert.pem and cert.key, issued for the host in RDPGW_SERVER__GATEWAY_ADDRESS. That is, put certificates into /var/lib/docker/volumes/conf/_data/. Normally, most of the stuff should be configured automatically by ACME client, TLS traffic terminated by ingress reverse proxy, and you would use RDPGW_SERVER__TLS=disable instead.

Third note: really, look into using docker compose as @pbvdven describes.

Efreak commented 1 month ago

I'm getting the same issues. I'm following a guide that claims to follow the repo here, but it's simply not working. I don't understand how to get it to work. I can't request for help from the blog post linked[^1].

I am also trying to change the default ports here: I can't use ports 80 and 443 (or 8080) because I already have servers listening on these ports for both public and private addresses, and cannot stop them (they're used by multiple other VMs)

Configuration details - Replaced/removed configuration items include either Unique or Reused. - Anything with Unique in it is not reused anywhere else (mostly encryption keys) - Anything with Reused in it is identical across files (mostly subdomains)
My docker-compose.yml ```yaml version: "3.9" services: postgres: container_name: db image: "postgres:14.4" restart: always healthcheck: test: [ "CMD", "pg_isready", "-q", "-d", "postgres", "-U", "postgres" ] timeout: 45s interval: 10s retries: 10 volumes: - ./postgres_data:/var/lib/postgresql/data - ./sql:/docker-entrypoint-initdb.d/:ro # turn it on, if you need run init DB environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: keycloak POSTGRES_HOST: postgres networks: - pgsql keycloak: container_name: keycloak image: quay.io/keycloak/keycloak command: ['start', '--proxy', "edge"] restart: always depends_on: postgres: condition: service_healthy environment: JAVA_OPTS_APPEND: -Dkeycloak.profile.feature.upload_scripts=enabled KC_DB_PASSWORD: postgres KC_DB_URL: "jdbc:postgresql://postgres/keycloak" KC_DB_USERNAME: postgres KC_DB: postgres KC_HEALTH_ENABLED: 'true' KC_HTTP_ENABLED: 'true' KC_METRICS_ENABLED: 'true' KC_HOSTNAME_STRICT_HTTPS: false KC_HOSTNAME: rdgateway-keycloak.ReusedDomain PROXY_ADDRESS_FORWARDING: 'true' KEYCLOAK_ADMIN: UniqueUsername KEYCLOAK_ADMIN_PASSWORD: UniquePassword healthcheck: test: ["CMD-SHELL", "exec 3<>/dev/tcp/127.0.0.1/8080;echo -e \"GET /health/ready HTTP/1.1\r\nhost: http://localhost\r\nConnection: close\r\n\r\n\" >&3;grep \"HTTP/1.1 200 OK\" <&3"] interval: 10s retries: 10 start_period: 20s timeout: 10s ports: - "8280:8080" - "8287:8787" # debug port networks: - pgsql - keycloak rdpgw: image: bolkedebruin/rdpgw:latest restart: always container_name: rdpgw ports: - "8180:80" - "8143:443" volumes: - ./rdpgw.yaml:/opt/rdpgw/rdpgw.yaml depends_on: keycloak: condition: service_healthy networks: - keycloak networks: pgsql: driver: bridge keycloak: driver: bridge ```
My rdpgw.yaml ```yaml Server: Tls: disable DisableTLS: true GatewayAddress: rdpgw.ReusedDomain Port: 8180 Hosts: - localhost:3389 - UniqueDomain:3389 # this is set in the hosts file to resolve to a VM ip RoundRobin: any SessionKey: "Unique32Chars" SessionEncryptionKey: "Unique32Chars" Authentication: - openid OpenId: ProviderUrl: http://rdgateway-keycloak.ReusedDomain/realms/rdpgw ClientId: rdpgw ClientSecret: UniqueGUID Client: UsernameTemplate: "{{ username }}" NetworkAutoDetect: 1 BandwidthAutoDetect: 1 ConnectionType: 6 SplitUserDomain: true Security: PAATokenSigningKey: "Unique32Chars" PAATokenEncryptionKey: "Unique32Chars" UserTokenEncryptionKey: "Unique32Chars" VerifyClientIp: false Caps: TokenAuth: true IdleTimeout: 10 EnablePrinter: true EnablePort: true EnablePnp: true EnableDrive: true EnableClipboard: true ```
Caddy config (running under windows host) ```yaml rdgateway-keycloak.ReusedDomain:443 { # Working TLS config removed (this is the same config used on other subdomains, it adds lets encrypt and integrates with DNS api) reverse_proxy 127.0.0.1:8280 } rdpgw.ReusedDomain:443 { # Working TLS config removed (this is the same config used on other subdomains, it adds lets encrypt and integrates with DNS api) reverse_proxy 127.0.0.1:8180 } ```

I cannot connect on any of the following urls:

[^1]: I got a database connection error once, and now other pages on the site won't load; I think that specific post may be cached.

My intended use case is self-hosting RDP access to my personal computer and some virtual machines on it without having to run a full VPN server for security; rather than using TLS termination inside any of the containers, I wish to use the native install of caddy that I've got running as a windows service (this is currently working for such things as airsonic, plex, calibre, and bubbleupnp, as well as several applications with ports forwarded from virtual machines). I've never used docker before, this is my first project using it, so please assume that I have no idea what I'm doing here (I feel like I'm probably missing something super simple).

If it's possible to set this up using WSL's mirrored networking enabled, that would also be helpful, but that's rather out of scope here (I'd like to use WSL mirrored networking for other services).

bolkedebruin commented 1 month ago

The rdpgw server only responds to “http://rdpgw.ReusedDomain:8180/connect” over http in your case as per documentation. This should redirect you to your keycloak server for authentication. MS Clients require https so your TLS termination should work.

If you cannot connect to either your keycloak installation or rdpgw, you are misconfiguring them with either IP/port or config.

Mikle-Bond commented 1 month ago

@Efreak

In caddy you redirect rdpgw to 127.0.0.1:8180, and then in docker-compose.yml you port-forward that port to 80. But in rdpgw.yml you set server to listen on 8180 again. Either change that last value to match 80, or set all to 8180.

Then, also in rdpgw.yml the OpenId.ProviderUrl should be reachable on your host, via curl or browser. In your case, that means caddy, and it will perform TLS termination, so at least change it to https://.... Also try adding log statement in caddy config and curl to it.

On the same note, try adding https:// scheme explictly in Server.GatewayAddress too.

The image of keycloak has curl in it, so I beleive the tricky shell commands in health checks can be simplified. Apart from that, the only significant difference from my configs I see is the use of start-dev in command instead of start. Maybe try that.

Also, I have built the rdpgw myself. I can't remember why tho. Maybe there was something wrong with the public image. I'll attach relevant part of my config. Maybe you'll see something else that is different.

My config Note: I've used caddy's self-signed certificate authority, so I had to install its root certificate into rdpgw's container. the `*default` thing in the config is called Yaml anchor, and it has stuff like `restart: always`, network and logging configs. ```yaml populate-certs: <<: *default image: alpine init: true entrypoint: ["sh", "-c"] command: - | apk add ca-certificates mkdir -p /usr/local/share/ca-certificates/ cp /data/caddy/pki/authorities/local/*.crt /usr/local/share/ca-certificates/ update-ca-certificates exec sleep infinity volumes: - data_caddy:/data:ro - cert_caddy:/etc/ssl/certs rdpgw: <<: *default labels: *simple_expose build: context: https://github.com/bolkedebruin/rdpgw.git#:/dev/docker volumes: - cert_caddy:/etc/ssl/certs:ro expose: [80] environment: RDPGW_SERVER__GATEWAY_ADDRESS: https://rdpgw.${BASE_DOMAIN} RDPGW_SERVER__PORT: "80" RDPGW_SERVER__TLS: disable RDPGW_OPEN_ID__PROVIDER_URL: https://keycloak.${BASE_DOMAIN}/auth/realms/rdpgw depends_on: - keycloak keycloak: <<: *default labels: *simple_expose image: quay.io/keycloak/keycloak:latest volumes: - /config/attempt/realm-export.json:/opt/keycloak/data/import/realm-export.json environment: KEYCLOAK_USER: admin KEYCLOAK_PASSWORD: admin KEYCLOAK_ADMIN: admin KEYCLOAK_ADMIN_PASSWORD: admin KC_PROXY: edge expose: [8080] command: - start-dev - --import-realm - --http-relative-path=/auth healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/auth"] interval: 30s timeout: 3s retries: 10 start_period: 5s ```