Tailscale上でRustDeskを使う

Tailscaleのネットワーク上に、RustDeskサーバ、接続するクライアントA、接続されるクライアントBがある場合、少々工夫すると高速な接続とリレーサーバを介さないデータ転送をすることができる。

前提条件

前提条件としては、上に書いたように、自前のRustDeskサーバを立ち上げること、接続する側・される側のマシンもサーバと同じTailscaleネットワーク内にあることだ。

Tailnet内のみの接続

同じTailnet内にあるため、マシンA・Bの間のデータ転送にはリレーサーバが必要ない。そのため、以下のようにID/ランデブーサーバのみを起動すればよい。

services:
  hbbs:
    container_name: hbbs
    ports:
      - 21115:21115
      - 21116:21116
      - 21116:21116/udp
      - 21118:21118
    image: rustdesk/rustdesk-server:latest
    command: hbbs -k password
    volumes:
      - ./data:/root
    restart: unless-stopped

password部分は適当なパスワードにする。このパスワードを知らない場合には接続できない(実際には、「接続する」側のみにパスワード指定が必要。もちろんされる側に指定しておいてもよい)。

クライアント側設定は以下のように簡単だ。passwordは先のものを指定する。

このサーバのTailnet内での固定IPアドレスを仮に100.64.0.1として以下に示すが、TailscaleのDNSにおいて、100.64.0.1に適当な名前が付けられている場合はそれを指定すればよい。

これだけである。後は普通に相手先に接続すればよい。

※クライアント側は、サーバをTailnet内のIPで参照しなければならない。そうすることにより、クライアント側のTailnet内のIPがサーバ側に伝えられる。

Tailnet以外のマシンも対象にしたいとき

Tailnet内のマシンは自分のものだけか、あるいは社内のものだけだろうが、同じサーバを使って他のマシンにも接続したい場合もあるだろう。その場合は以下の条件になる。

  • 接続する側・される側の、両方が同じID/ランデブーサーバを使わないといけない。そのため、このサーバにTailnet外部から何らかの方法でアクセスできる必要がある。つまり、グローバルIPアドレスか、ドメインが必要になる。
  • おそらくはリレーサーバが必要になるので、これも起動しておく。

このサーバのドメインをrustdesk.example.comとする。この場合のdocker-compose.ymlは以下になる。

version: '3'

networks:
  rustdesk-net:
    external: false

services:
  hbbs:
    container_name: hbbs
    ports:
      - 21115:21115
      - 21116:21116
      - 21116:21116/udp
      - 21118:21118
    image: rustdesk/rustdesk-server:latest
    command: hbbs -r rustdesk.example.com:21117  -k password
    volumes:
      - ./data:/root
    networks:
      - rustdesk-net
    depends_on:
      - hbbr
    restart: unless-stopped

  hbbr:
    container_name: hbbr
    ports:
      - 21117:21117
      - 21119:21119
    image: rustdesk/rustdesk-server:latest
    command: hbbr -k password
    volumes:
      - ./data:/root
    networks:
      - rustdesk-net
    restart: unless-stopped

Tailnet内のRustDeskクライアントの指定は以前と同じで良いが、Tailnet外のクライアントでは、以下のようにする必要がある。

これで内外ともに同じID/ランデブーサーバが使われることになる。さらに、互いに直接接続ができない場合は、リレーサーバが使われる。

リレーサーバの使用確認

上のリレーサーバ有りのケースで、実際にリレーサーバが使われているか否かは、「docker-compose logs -f」でログを見ているとわかる。以下のようなエントリが出るからである。

hbbr    | [2023-04-01 05:47:37.095594 +00:00] INFO [src/relay_server.rs:451] New relay request c8601d37-f73e-4b42-9dcd-8********* from [::ffff:123.***.**.***]:64700

リレーサーバが使われている状態で、サーバをダウンさせると当然だが切断してしまう。その一方、リレーサーバが使われていない場合は、サーバを落としても接続が切れないことがわかる。つまり、ID/ランデブーサーバは、これも当然だが、最初の接続の時にしか使われないのだ。

※ちなみに、マシンどうしのランデブーに関しては、何のログも出力されないようだ。デバッグ用フラグを指定する方法も不明。ここに指定方法があるのだが、これをやっても変化がない。

追記:マニュアルは間違いで、.envでは効果がない。デバッグフラグを指定するには、以下のようにする。この例では、デバッグレベルをトレースにするとともに、リレーサーバを強制している。

docker-composeで起動した後は、docker-compose logs -fとすれば、トレース状態が見える。

version: '3'

networks:
  rustdesk-net:
    external: false

services:
  hbbs:
    container_name: hbbs
    ports:
      - 21115:21115
      - 21116:21116
      - 21116:21116/udp
      - 21118:21118
    image: rustdesk/rustdesk-server:latest
    environment:
      - "RUST_LOG=trace"
      - "ALWAYS_USE_RELAY=Y"
    command: hbbs -r rustdesk.example.com:21117  -k password
    volumes:
      - ./data:/root
    networks:
      - rustdesk-net
    depends_on:
      - hbbr
    restart: unless-stopped

  hbbr:
    container_name: hbbr
    ports:
      - 21117:21117
      - 21119:21119
    image: rustdesk/rustdesk-server:latest
    environment:
      - "RUST_LOG=trace"
    command: hbbr -k password
    volumes:
      - ./data:/root
    networks:
      - rustdesk-net
    restart: unless-stopped

あるいは、env_fileで指定する方法もある。

デフォルトの状態で接続が非常に遅くなる理由

自前のサーバを使わずにデフォルトの状態でRustDeskクライアントを使う場合、ときには非常に接続が遅くなったり、何度やり直しても接続できなかったりするのだが、おそらくこれは、リレーサーバが必要な時にそれが空いていないせいではないかと推測される。

ID/ランデブーサーバのやることは大したことではなく、単純に待ち合わせ(ランデブー)なのだが、リレーが必要な場合には、全データ(画像、音声、操作データ)がそのリレーサーバを経由するからだ。

IDはどうやって決めているのか?

マシンにつけられるID(123 456 789のようなもの)は、特にバッティングしないように管理されているものではないらしく、好きな値に変更できるらしい。つまり、ランダムに決められていると思われる。

これは、Linuxの場合、`/.config/rustdesk/RustDesk.tomlというテキストファイルに記述がある。ここを適当に書き換えて好きな数字にすることもできるようだ。

ただし、実際にIDがバッティングしてしまった場合にどう対処されるのかは不明。