RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1605969
Accepted
 Antisfera
Antisfera
Asked:2025-01-31 07:43:34 +0000 UTC2025-01-31 07:43:34 +0000 UTC 2025-01-31 07:43:34 +0000 UTC

(webSocket)我无法从手机连接到服务器。代码#

  • 772

该服务器有一个控制台应用程序。服务器在 VPS 上运行。一个wifi上有两个设备。第一个是一台电脑。我可以轻松地从那里登录。通过 unity 内部为 android 构建 unity。第二个是我的安卓。我无法从它连接到服务器。

await webSocket.ConnectAsync(new Uri("ws://45.143.93.104:8080"), CancellationToken.None);

我得出的结论是,我需要一个 Android 的 SSL/TLS 证书才能允许连接。但我不知道该怎么做。也涉及 IP。我没有域名...

有人能给我一些建议吗?这个证书是强制性的吗?没有其他办法了吗?稍后是否需要通过WSS来做?

c#
  • 1 1 个回答
  • 49 Views

1 个回答

  • Voted
  1. Best Answer
    Uranus
    2025-01-31T13:13:52Z2025-01-31T13:13:52Z

    Android 9+ (Pie,API 28)默认阻止所有未加密的(ws://, )连接。http://可以通过添加权限来解决此问题AndroidManifest.xml:

    <application android:usesCleartextTraffic="true" />
    

    但这只是临时解决办法,因为谷歌正在积极推动wss://,未来可能会有更严格的限制(如同http://)。最好立即使用它,wss://以避免将来出现问题。

    如果您仍然需要它,您可以使用 Let's Encrypt 通过Nginxwss://转发 WebSocket - 然后您将毫无问题地获得真正的 WebSocket 。 Nginx 接受并且服务器继续在 VPS 内部运行。wss://wss://ws://

    Let's Encrypt 不为 IP 地址颁发证书,因此您需要注册一个域名并将其指向您的服务器。如果您不想这样做,您可以使用自签名证书。 Android 不信任自签名证书,因此您必须手动将其添加到每个设备。他们说您可以配置 Android 应用程序以信任自签名证书,这样您就不必手动将其添加到每个设备。但是我没有找到 Unity 的说明,只有这一个:使用 Android Native、Android Studio 和 retrofit 在本地网络中信任我自己的自签名证书。


    安装 Nginx

    sudo apt update
    sudo apt install nginx -y
    

    让我们检查一下它是否有效:

    systemctl status nginx
    

    如果没有运行,请运行它:

    sudo systemctl enable nginx
    sudo systemctl start nginx
    

    我们假设您的 C# 应用程序正在某个端口上运行8080并且正在监听ws://123.123.123.123:8080。让我们检查服务器是否在本地运行:

    curl -i ws://localhost:8080
    

    (注意)此示例curl用作快速端口可用性检查,而不是成熟的 WebSocket 客户端。curl并不真正支持 WebSocket,因此您会收到如下错误:

    HTTP/1.1 400 Bad Request
    

    这是正常的,如果服务器有响应,则表示端口是开放的。

    如果 WebSocket 服务器响应ws://123.123.123.123:8080但无法访问ws://localhost:8080,则服务器仅在外部接口上监听。用于0.0.0.0使服务器监听所有连接。

    现在让我们从 Let's Encrypt 设置一个免费证书(替换example.com为您的域名):

    sudo apt install certbot python3-certbot-nginx -y
    sudo certbot certonly --nginx -d example.com
    

    如果您只有 IP(没有域名),Let's Encrypt 将不会颁发证书。在这种情况下,您将必须使用自签名证书(我将在最后解释)。

    证书将保存在:

    • /etc/letsencrypt/live/example.com/fullchain.pem
    • /etc/letsencrypt/live/example.com/privkey.pem

    检查证书是否已安装:

    sudo certbot renew --dry-run
    

    将 Nginx 设置为 WebSocket 反向代理

    我们使用这里描述的协议切换机制:WebSocket 代理。

    让我们创建一个将重定向wss://到的Nginx 配置ws://:

    sudo nano /etc/nginx/sites-available/websocket
    

    添加配置(不要忘记将其替换example.com为您的域名):

    server {
        listen 443 ssl;
        server_name example.com;
    
        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
        location / {
            proxy_pass http://localhost:8080/;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "Upgrade";
            proxy_set_header Host $host;
        }
    }
    
    server {
        listen 80;
        server_name example.com;
        return 301 https://$host$request_uri;
    }
    

    激活配置:

    sudo ln -s /etc/nginx/sites-available/websocket /etc/nginx/sites-enabled/
    

    让我们检查一下语法:

    sudo nginx -t
    

    重新启动Nginx:

    sudo systemctl restart nginx
    

    现在您可以连接到wss://example.com而不是ws://123.123.123.123:8080。

    通过(WebSocket 客户端)检查wscat:

    npm install -g wscat
    wscat -c wss://example.com
    

    如果一切正常,你应该会看到连接。


    没有域名怎么办?

    您可以生成自签名证书:

    sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
    -keyout /etc/ssl/private/nginx-selfsigned.key \
    -out /etc/ssl/certs/nginx-selfsigned.crt
    

    然后替换 Nginx 配置:

    ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
    ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
    

    缺点:必须手动将此类证书添加到应用程序中。


    是否有可能在没有 Nginx 的情况下将证书连接到 C# 服务器?

    您可以配置您的 WebSocket 服务器以直接使用 Let's Encrypt 证书。

    安装Certbot并运行命令:

    certbot certonly --standalone -d example.com
    

    证书存储在/etc/letsencrypt/live/example.com/fullchain.pem和中privkey.pem。将文件转换pem为 PFX:

    openssl pkcs12 -export -out certificate.pfx -inkey privkey.pem -in fullchain.pem
    

    现在您可以下载SslStream证书:

    var certificate = new X509Certificate2("certificate.pfx", "your_password");
    
    var listener = new TcpListener(IPAddress.Any, 443);
    listener.Start();
    
    while (true)
    {
        var client = await listener.AcceptTcpClientAsync();
        var sslStream = new SslStream(client.GetStream());
        await sslStream.AuthenticateAsServerAsync(certificate);
    }
    

    如果您将ASP.NET Core 与 Kestrel结合使用,请参阅文档的SSL/TLS 协议部分。

    Let's Encrypt 颁发的证书有效期为 90 天,因此您需要自动续订。按计划执行命令:

    certbot renew --quiet
    

    您可以将其添加到cron ( crontab -e) 中:

    0 0 * * 1 certbot renew --quiet && systemctl restart myapp
    

    优点:

    • 无第三方代理

    缺点:

    • 证书需要手动(或自动)更新
    • 该服务器必须可以从外部访问(Certbot 需要端口80或443)。
    • 0

相关问题

  • 使用嵌套类导出 xml 文件

  • 分层数据模板 [WPF]

  • 如何在 WPF 中为 ListView 手动创建列?

  • 在 2D 空间中,Collider 2D 挂在玩家身上,它对敌人的重量相同,我需要它这样当它们碰撞时,它们不会飞向不同的方向。统一

  • 如何在 c# 中使用 python 神经网络来创建语音合成?

  • 如何知道类中的方法是否属于接口?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5