Icecast2在nginx下运行无法连接

iyzzxitl  于 2023-03-22  发布在  Nginx
关注(0)|答案(4)|浏览(93)

我想开始说的是,我已经找遍了所有地方来寻找这个问题的答案,它只是看起来好像没有其他人遇到这个问题,或者没有人做这个问题。所以,我最近在我的Debian服务器上安装了icecast 2,事情是我完全能够从我的本地网络广播到我的服务器,连接到它的本地IP端口8000,并在互联网上听到流 www.example.com 因为我用nginx代理,到目前为止没有任何问题。问题在于当我想广播到我用nginx给的域名stream.example.com
我有两个理论,一个是代理没有给icecast源IP,所以它认为它是从www.example.com开始广播127.0.0.1,另一个是nginx对数据流做了一些奇怪的事情,因此没有向icecast提供正确的格式。
有什么想法吗?先谢了!
下面是nginx的配置

server {
    listen 80;
    listen [::]:80;
    server_name radio.example.com;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Real-IP $remote_addr;

    location / {
            proxy_pass http://127.0.0.1:8000/radio;
            subs_filter_types application/xspf+xml audio/x-mpegurl audio/x-vclt text/css text/html text/xml;
            subs_filter ':80/' '/' gi;
            subs_filter '@localhost' '@stream.example.com' gi;
            subs_filter 'localhost' $host gi;
            subs_filter 'Mount Point ' $host gi;
    }
}

server {
    listen 80;
    listen [::]:80;
    server_name stream.example.com;

    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Real-IP $remote_addr;
    location / {
            proxy_pass http://localhost:8000/;
            subs_filter_types application/xspf+xml audio/x-mpegurl audio/x-vclt text/css text/html text/xml;
            subs_filter ':8000/' ':80/' gi;
            subs_filter '@localhost' '@stream.example.com' gi;
            subs_filter 'localhost' $host gi;
            subs_filter 'Mount Point ' $host gi;
    }
}

这是我在icecast error.log上得到的

[2018-08-10  14:15:45] INFO source/get_next_buffer End of Stream /radio
[2018-08-10  14:15:45] INFO source/source_shutdown Source from 127.0.0.1 at "/radioitavya" exiting
mpbci0fu

mpbci0fu1#

不知道这有多少是直接相关的操作员的问题,但这里有一些片段,从我的配置。
这些是我的块的基础,通过端口443上的SSL向客户端提供流。
在第一个位置块中,任何URI不是/ogg、/128、/192或/320的请求都会被重写,以防止客户端访问Icecast服务器的任何输出,而不是流本身。

server {
  listen 443 ssl http2;
  server_name stream.example.com;
  ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
  ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

  location / {
    rewrite  ~*(ogg) https://stream.example.com/ogg last;
    rewrite  ~*([0-1][0-5]\d) https://stream.example.com/128 last;
    rewrite  ~*(?|([1][6-9]\d)|([2]\d\d)) https://stream.example.com/192 last;
    rewrite  ~*([3-9]\d\d) https://stream.example.com/320 break;
    return  https://stream.example.com/320;
  }

  location ~ ^/(ogg|128|192|320)$ {
    proxy_bind $remote_addr transparent;
    set $stream_url http://192.168.100.100:8900/$1;
    types        { }
    default_type audio/mpeg;
    proxy_pass_request_headers on;
    proxy_set_header Access-Control-Allow-Origin *;
    proxy_set_header Host $host;
    proxy_set_header Range bytes=0-;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_buffering off;
    tcp_nodelay on;
    proxy_pass $stream_url;
  }
}

使用transparent标志设置proxy_bind
允许从非本地IP地址(例如,客户端的真实的IP地址)发出到代理服务器的传出连接
这解决了日志/统计中的本地IP地址而不是客户端IP的问题,为此,您还需要重新配置内核路由表以捕获从上游服务器发送的响应并将其路由回Nginx。
这需要root访问权限和对Linux网络配置的合理理解,我很感激不是每个人都有。我也很感激不是每个使用Icecast并可能想要反向代理的人都会阅读此内容。一个更好的解决方案是使Icecast对Nginx更友好,所以我试了一下。
我从github上克隆了Icecast并查看了代码。我可能错过了一些,但这些行看起来与我相关:

./src/logging.c:159:  client->con->ip,
./src/admin.c:700:    xmlNewTextChild(node, NULL, XMLSTR(mode == OMODE_LEGACY ? "IP" : "ip"), XMLSTR(client->con->ip));

对于不支持PROXY协议的服务器,Nginx将客户端IP上行的默认方法是通过X-Real-IP头。Icecast似乎使用client->con->ip的值来记录侦听器IP。让我们稍微改变一下。我添加了这个:

const char *realip;
realip = httpp_getvar (client->parser, "x-real-ip");
if (realip == NULL)
  realip = client->con->ip;

并将前面的行更改为:

./src/logging.c:163:  realip,
./src/admin.c:700:    xmlNewTextChild(node, NULL, XMLSTR(mode == OMODE_LEGACY ? "IP" : "ip"), XMLSTR(realip));

然后我根据文档从源代码构建了Icecast。在我的Nginx conf中的proxy_set_header X-Real-IP $remote_addr;指令正在传递客户端IP,如果你有额外的上游服务器也处理请求,你将需要添加一些set_real_ip_from指令指定每个IP,real_ip_recursive on;并使用$proxy_add_x_forwarded_for;,它将捕获处理请求的每个服务器的IP地址。
启动了我的新Icecast构建,这似乎工作得很完美。如果X-Real-IP头部被设置,那么Icecast将其记录为侦听器IP,如果没有,那么它将记录客户端请求IP,因此它应该适用于反向代理和正常设置。似乎太简单了,也许我错过了一些@TBR?
好了,现在你应该已经有了通过SSL提供的工作监听器流,并有了正确的统计数据/日志。你已经完成了困难的部分。现在让我们向它们传输一些东西吧!
由于在Nginx中添加了stream模块,因此无论是否使用PUT/SOURCE,处理传入连接都很简单。
如果你在stream指令中指定了一个服务器,Nginx会简单地将传入的流隧道传输到上游服务器,而不检查或修改数据包。Nginx streams config lessons 101就是你所需要的:

stream {

  server {
    listen pub.lic.ip:port;
    proxy_pass ice.cast.ip:port;
  }
}

我猜人们在Nginx中使用SOURCE连接时可能会遇到的一个问题是在Nginx配置中指定了错误的端口。不要感到难过,Shoutcast v1只是有点奇怪。要记住的一点是:

  • 它实际上将尝试连接到端口+1,而不是您在客户端编码器中指定的端口

因此,如果您使用端口8000进行传入连接,请使用Shoutcast v1协议在客户端编码器中将端口设置为7999,或者使用2个块设置Nginx流指令,一个用于端口8000,一个用于端口8001。
您的Nginx安装必须使用stream模块构建,它不是标准构建的一部分。不确定?运行:

nginx -V 2>&1 | grep -qF -- --with-stream && echo ":)" || echo ":("

如果你看到一个笑脸,你就可以开始了。如果没有,你就需要构建Nginx并包含它。许多仓库都有一个nginx-extras包,其中包含stream模块。
几乎完成了,我们现在需要的就是访问管理页面。我从https://example.com/icecast/提供这些,但Icecast使用根路径生成管理页面链接中的所有URI,不包括icecast/,所以它们不会工作。让我们使用Nginx子过滤器模块将icecast/添加到返回页面中的链接来解决这个问题:

location /icecast/ {
  sub_filter_types text/xhtml text/xml text/css;
  sub_filter 'href="/'  'href="/icecast/';
  sub_filter 'url(/'  'url(/icecast/';
  sub_filter_once off;
  sub_filter_last_modified on;
  proxy_set_header Accept-Encoding "";
  proxy_pass http://ice.cast.ip:port/;
}

proxy_pass http://ice.cast.ip:port/;末尾的斜杠对于此操作至关重要。
如果proxy_pass指令被指定为server:port,则完整的原始客户端请求URI将被附加并传递给上游服务器。如果proxy_pass附加了任何URI(即使只是/),则Nginx将替换客户端请求URI中与位置块匹配的部分(在本例中为/icecast/),并将其附加到proxy_pass。因此,通过附加斜杠,对https://example.com/icecast/admin/的请求将被代理到http://ice.cast.ip:port/admin/
最后,我不想让我的管理员页面被世界访问,只有我的IP和LAN,所以我也在上面的位置包括这些:

allow 127.0.0.1;
allow 192.168.1.0/24;
allow my.ip.add.ress;
deny all;

就是这样。

sudo nginx -s reload

玩得开心。

qyswt5oh

qyswt5oh2#

tl;dr -不要反向代理Icecast。

Icecast由于各种原因最好不要反向代理。它是一个专门构建的HTTP服务器,而通用HTTP服务器往往会在连续HTTP流的复杂性方面存在重大问题。
人们总是喜欢尝试,但总是以各种方式失败。

oknwwptz

oknwwptz3#

这条线...

subs_filter '@localhost' '@stream.example.com' gi;

应该...

subs_filter '@localhost' '@example.com' gi;

我不熟悉nginx,所以我最好的猜测是这一行将radio.example.com链接到example.com的主站点。通过添加stream.example.com,您会将其定向到一个不存在的站点,从而使其混淆。
我从配置文件posted here中得到了这个:
不管怎样,试试也无妨。

7cwmlq89

7cwmlq894#

重新编译icecast2是一个非常好的主意。不幸的是,目前的文件夹
https://github.com/xiph/Icecast-Server/tree/master/src/common
是空的。
这个缺少的子模块抛出未定义的常量SOCK_FAMILY_* 的错误
有人知道它的替代回购或来源。

相关问题