bolkedebruin / rdpgw

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

Documentation seems to be unclear on options 'any' and 'roundRobin' #35

Closed alphabet5 closed 1 year ago

alphabet5 commented 2 years ago

From the docs it reads like having 'any' in the list of hosts should allow you to modify the rdp file and connect to any host.

  # Allow the user to connect to any host (insecure)
  - any 

Trying this and modifying the rdp file to connect to 10.111.111.101:3389 gives the following error.

There was a problem connecting to the remote resource. Ask your network administrator for help.

Looking at the logs, it's getting blocked because the host does not match the token host 'any'.

2022/03/15 02:09:05 Starting remote desktop gateway server
2022/03/15 02:10:29 Client handshakeRequest from 10.111.111.13
2022/03/15 02:10:29 major: 1, minor: 0, version: 0, ext auth: 2
2022/03/15 02:10:29 Tunnel create
2022/03/15 02:10:29 Tunnel auth
2022/03/15 02:10:29 Channel create
2022/03/15 02:10:29 Client specified host 10.111.111.101:3389 does not match token host any
2022/03/15 02:10:29 Not allowed to connect to 10.111.111.101:3389 by policy handler

If I add in 10.111.111.101:3389 to the list of hosts the .rdp file downloaded seems to be for a random host with 'roundRobin' set to false. When the host is changed to another host that is specified in the configuration file, I still receive the 'not allowed to connect' message.

2022/03/15 02:23:04 Client handshakeRequest from 10.111.111.13
2022/03/15 02:23:04 major: 1, minor: 0, version: 0, ext auth: 2
2022/03/15 02:23:04 Tunnel create
2022/03/15 02:23:04 Tunnel auth
2022/03/15 02:23:04 Channel create
2022/03/15 02:23:04 Client specified host 10.111.111.101:3389 does not match token host 10.111.111.103:3389
2022/03/15 02:23:04 Not allowed to connect to 10.111.111.101:3389 by policy handler

Example config file:

server:
  certFile: /certs/tls.crt
  keyFile: /certs/tls.key
  gatewayAddress: rdpgw.demo.cybertrol.app
  port: 9443
  hosts:
    - 10.111.111.101:3389
    - 10.111.111.102:3389
    - 10.111.111.103:3389
    - 10.111.111.104:3389
    - 10.111.111.105:3389
    - 10.111.111.106:3389
    - any
  roundRobin: false
  sessionKey: thisisasessionkeyreplacethisjetz
  sessionEncryptionKey: thisisasessionkeyreplacethisnunu
caps:
  smartCardAuth: false
  tokenAuth: true
  idleTimeout: 60
  enablePrinter: false
  enablePort: false
  enablePnp: false
  enableDrive: false
  enableClipboard: true
openId:
  providerUrl: https://auth.demo.domain.com
  clientId: rdpgw
  clientSecret: 01cd304c-6f43-4480-9479-618eb6fd578f
client:
  usernameTemplate: "domain\\{{ username }}"
  networkAutoDetect: 0
  bandwidthAutoDetect: 1
  ConnectionType: 6
  SplitUserDomain: true
security:
  PAATokenSigningKey: prettypleasereplacemeinproductio
  UserTokenEncryptionKey: prettypleasereplacemeinproductio
  EnableUserToken: true
  VerifyClientIp: false

With that I have a few questions.

alphabet5 commented 2 years ago

Looks like the default config right now is to just randomly select a host.

    // do a round robin selection for now
    rand.Seed(time.Now().Unix())
    host := c.Hosts[rand.Intn(len(c.Hosts))]
    host = strings.Replace(host, "{{ preferred_username }}", userName, 1)

Any idea how it would be best to select different hosts? ?host=1.2.3.4%3A3389 maybe?

An example error with the 'any' under hosts.

2022/04/22 02:16:59 Client specified host 1.2.3.4:3389 does not match token host 192.168.1.2:3389
2022/04/22 02:16:59 Not allowed to connect to 1.2.3.4:3389 by policy handler

I've modifed the VerifyServerFunc with

if s.RemoteServer != host && !(Contains(config.Conf.Server.Hosts, "any"))

And it seems to work just fine now. However, it looks like 'any' might need to be skipped when choosing the random host to connect to, as 'any' isn't accessible.

bolkedebruin commented 1 year ago

Yes, this isn't working as expected or documented :-). The approach I would like to take is to allow specifying a host "pre-download" time, so that it can still be verified keeping certain security guarantees in place.

bolkedebruin commented 1 year ago

This has been solved now in master. hostselection can now be roundrobin, signed, unsigned or any. For your use case you probably want signed or unsigned.