lantongxue / rustdesk-api-server-pro

🚀This is an open source Api server based on the open source RustDesk client, the implementation of the client all Api interfaces, and provides a Web-UI for the management of data.
https://sephp.com/open-source/rustdesk-api-server-pro/
GNU Affero General Public License v3.0
57 stars 10 forks source link

/admin returns 404 #15

Closed innovara closed 2 weeks ago

innovara commented 3 weeks ago

Maybe related to https://github.com/lantongxue/rustdesk-api-server-pro/issues/4

I was testing rustdesk-api-server-pro with a more advanced configuration but, since I am struggling with a basic issue, I've literally gone back to the most basic of them, following the instructions as liteally as possible, and the location /admin always returns 404 even without any proxy intervention.

server.yaml

signKey: "sercrethatmaycontainch@r$32chars" # this is the token signing key. change this before start server
db:
  driver: "sqlite"
  dsn: "./server.db"
  timeZone: "Asia/Shanghai" # setting the time zone fixes the database creation time problem
  showSql: true

  # driver: "mysql"
  # dsn: "root:123@tcp(localhost:3306)/test?charset=utf8mb4"
httpConfig:
  printRequestLog: true
  port: ":8080" # api server port
jobsConfig:
  deviceCheckJob:
    duration: 30

container

docker run --name rustdesk-api-server-pro -d -e ADMIN_USER=admin -e ADMIN_PASS=apassword -p 8080:8080 -v /path/to/server.yaml:/app/server.yaml ghcr.io/lantongxue/rustdesk-api-server-pro:latest

nginx configuration for the server

server {
  server_name rustdesk.example.com;
  listen 443 ssl;
  listen [::]:443 ssl;
  root /var/www/html;
  index index.html index.htm index.nginx-debian.html;
#PROXY-START /api for rustdesk client
location ^~ /api
{
    proxy_pass http://127.0.0.1:8080;
    proxy_set_header Host 127.0.0.1;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header REMOTE-HOST $remote_addr;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_http_version 1.1;
    # proxy_hide_header Upgrade;

    add_header X-Cache $upstream_cache_status;
}
#PROXY-END/
#PROXY-START /admin for web-ui
location ^~ /admin
{
    proxy_pass http://127.0.0.1:8080/admin;
    proxy_set_header Host 127.0.0.1;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header REMOTE-HOST $remote_addr;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_http_version 1.1;
    # proxy_hide_header Upgrade;

    add_header X-Cache $upstream_cache_status;
}
#PROXY-END/
  ssl_certificate /etc/letsencrypt/live/rustdesk.example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/rustdesk.example.com/privkey.pem;
  include /etc/letsencrypt/options-ssl-nginx.conf;
  ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
  add_header Strict-Transport-Security "max-age=31536000" always;
# log
  access_log /var/log/nginx/rustdesk.example.com-access.log;
  error_log /var/log/nginx/rustdesk.example.com-error.log;
}

server {
  server_name rustdesk.example.com;
  listen 80;
  listen [::]:80;
  if ($host = rustdesk.example.com) {
    return 301 https://$host$request_uri;
  }
  return 404;
}

Container log when I try to connect to rustdesk.example.com/admin on a computer (the result on the client is 404)

[INFO] 2024/11/05 16:22 (404)▶ GET:/admin
Sec-Ch-Ua-Platform: ["Windows"]
Sec-Fetch-Mode: [navigate]
Sec-Fetch-User: [?1]
Cache-Control: [max-age=0]
Upgrade-Insecure-Requests: [1]
Sec-Ch-Ua: ["Chromium";v="130", "Google Chrome";v="130", "Not?A_Brand";v="99"]
Accept: [text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7]
Sec-Fetch-Site: [cross-site]
Accept-Encoding: [gzip, deflate, br, zstd]
X-Real-Ip: [580c:c70b:9af4:1a7c:5dfe:7bd5:fb91:5188]
Remote-Host: [580c:c70b:9af4:1a7c:5dfe:7bd5:fb91:5188]
Sec-Ch-Ua-Mobile: [?0]
User-Agent: [Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36]
Sec-Fetch-Dest: [document]
Accept-Language: [en-US,en;q=0.9]
X-Forwarded-For: [580c:c70b:9af4:1a7c:5dfe:7bd5:fb91:5188]
Connection: [close]

Container log when I try to connect to rustdesk.example.com/admin with an iPhone over cellular data (page is blank):

[INFO] 2024/11/05 16:18 (404)▶ GET:/admin
User-Agent: [Mozilla/5.0 (iPhone; CPU iPhone OS 18_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.1 Mobile/15E148 Safari/604.1]
Sec-Fetch-Dest: [document]
Sec-Fetch-Site: [none]
Sec-Fetch-Mode: [navigate]
Remote-Host: [28.25.241.124]
X-Real-Ip: [28.25.241.124]
Upgrade-Insecure-Requests: [1]
Priority: [u=0, i]
Accept-Encoding: [gzip, deflate, br]
Connection: [close]
Accept: [text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8]
X-Forwarded-For: [28.25.241.124]
Accept-Language: [en-GB,en;q=0.9]

Moreover, from the server hosting the container:

wget http://0.0.0.0:8080/admin

--2024-11-05 16:39:04--  http://0.0.0.0:8080/admin
Connecting to 0.0.0.0:8080... connected.
HTTP request sent, awaiting response... 404 Not Found
2024-11-05 16:39:04 ERROR 404: Not Found.

And the same command executed on the container:

docker exec -it rustdesk-api-server-pro wget http://0.0.0.0:8080/admin

Connecting to 0.0.0.0:8080 (0.0.0.0:8080)
wget: server returned error: HTTP/1.1 404 Not Found

However, if you use wget with http://0.0.0.0:8080 either on the host or the container, the index.html file that you get is what you would expect:

<!doctype html>
<html lang="zh-cmn-Hans">
  <head>
    <meta name="buildTime" content="2024-11-01 22:28:37">
    <meta charset="UTF-8" />
    <link rel="icon" href="/favicon.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="color-scheme" content="light dark" />
    <title>Rustdesk Api Server Pro</title>
    <script type="module" crossorigin src="/assets/index-h_rW8evI.js"></script>
    <link rel="stylesheet" crossorigin href="/assets/index-wPnY2Xu_.css">
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>

So it basically seems that soybean-admin or any of its components, I don't know enough about that to say, is not correctly set up to serve under /admin.

To confirm my suspicion, I set up nginx to proxy _pass / entirely, and the admin log in page loads under http://rustdesk.example.com (gets redirected to https://rustdesk.example.com/#/login)

server {
  server_name rustdesk.example.com;
  listen 443 ssl;
  listen [::]:443 ssl;
  root /var/www/html;
  index index.html index.htm index.nginx-debian.html;
#PROXY-START
location /
{
    proxy_pass http://127.0.0.1:8080;
    proxy_set_header Host 127.0.0.1;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header REMOTE-HOST $remote_addr;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_http_version 1.1;
    # proxy_hide_header Upgrade;

    add_header X-Cache $upstream_cache_status;
}
#PROXY-END/
  ssl_certificate /etc/letsencrypt/live/rustdesk.example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/rustdesk.example.com/privkey.pem;
  include /etc/letsencrypt/options-ssl-nginx.conf;
  ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
  add_header Strict-Transport-Security "max-age=31536000" always;
# log
  access_log /var/log/nginx/rustdesk.example.com-access.log;
  error_log /var/log/nginx/rustdesk.example.com-error.log;
}

server {
  server_name rustdesk.example.com;
  listen 80;
  listen [::]:80;
  if ($host = rustdesk.example.com) {
    return 301 https://$host$request_uri;
  }
  return 404;
}
lantongxue commented 3 weeks ago

If you have deployed it, just access http://yourserver:8080, /admin is the web-ui api, don't access /admin!

innovara commented 3 weeks ago

I am a bit confused with your response. Your advice is the opposite to the purpose of a reverse proxy and not fit for a production environment. Are you saying that you expect people to expose the entire API port to the world with no encryption whatsoever? The reverse proxy, in this case nginx, should receive the traffic from the client over TLS on port 443, and only pass requests to /api and /admin to the container or service running on port 8080.

Also, what is all the proxy configuration advice about then? I mean, you are advising to proxy_pass /admin but then now you are not supposed to use it? As I said, super confused.

lantongxue commented 3 weeks ago

First of all, this is a front-end and back-end separation of the project, the front-end needs to be deployed separately, and the interface needed by the front-end is /admin. Secondly, the purpose of the reverse proxy is to not expose the program itself listening port, and secondly, it can also provide traffic encryption. Finally, you can refer to the example in the documentation for the configuration file.

Special note: /api is for rustdesk client, /admin is for web-ui.

lantongxue commented 3 weeks ago

If you're using a docker deployment, then your nginx just needs to reverse proxy http://127.0.0.1:8080/ and that's it!

You no longer need to proxy /api and /admin.

innovara commented 3 weeks ago

First and foremost, thank you for your time and efforts. I am here to learn about your project but also to help you to develop it with feedback so please bear with me.

It makes less (production) sense to me as you add more coments but never mind. You DO want to proxy pass /api and /admin and nothing else. If you proxy pass all the traffic comming to nginx for that server, you are effectively exposing the listening port of the program itself and anyone can send any arbitrary string to your program because nginx will simply forward it.

The thing is that /api works perfectly with the proxy configuration. However, soybean-admin doesn't under /admin which is what I would expect. Even more so after seeing .env.prod. But somehow that's not happening. So you've got the back-end working under /api, as expected, and the front-end not working under /admin, as I would expect. Something is not set up correctly in the configuration of the front-end or the building of the image IMHO.

lantongxue commented 3 weeks ago

If you're using a docker deployment. Then nginx configs :

server {
  server_name rustdesk.example.com;
  listen 443 ssl;
  listen [::]:443 ssl;
  root /var/www/html;
  index index.html index.htm index.nginx-debian.html;

  location  /
  {
      proxy_pass http://127.0.0.1:8080;
      proxy_set_header Host 127.0.0.1;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header REMOTE-HOST $remote_addr;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection $connection_upgrade;
      proxy_http_version 1.1;
      # proxy_hide_header Upgrade;

      add_header X-Cache $upstream_cache_status;
  }
 #PROXY-END
}
innovara commented 2 weeks ago

Thank you, but I already knew that configuration would work. It's on my first post.

In the end, I reviewed the code and I figured out what needs changing for the front-end to be served under /admin, as I think it should be. It's a combination of using pnpm build --outDir dist/admin in the right places and VITE_BASE_URL=/admin. You can see the changes here: https://github.com/innovara/rustdesk-api-server-pro/commit/0535ef47cc860c4568f230cbf96bf94ef8ed6ad7#diff-bb53f101c061e0643cf840a86a20f6219980ad9fe7fdb054f4600db0589da512R1

Docker image if you want to test it: ghcr.io/innovara/rustdesk-api-server-pro:latest

With those changes you can have nginx to proxy pass /api which was already working and /admin, and nothing else, which is what your own documentation states but the application doesn't currently deliver.

lantongxue commented 2 weeks ago

Thank you