同一端口上的 icecast 和 apache(mod_proxy、mod_rewrite)

同一端口上的 icecast 和 apache(mod_proxy、mod_rewrite)

我有一个在端口 8000 上运行的 icecast 服务器。我可以从互联网以 LINK1(见下文)的形式顺利访问该服务器。此外,我创建了一个包含一些信息的小型 HTML 页面,其中还嵌入了 HTML5 音频播放器。如果以 http host dot domain dot com 的形式访问,则运行良好。

<html>
    <head>
        <title>Radio</title>
    </head>
    <body>
        <p>Some text</p>
        <audio controls>
          <source src="LINK1" type="audio/ogg">
        </audio>
    </body>
</html>

问题是,如果监听者的电脑上的端口 8000 被阻止,他们就听不到音频流。因此,我尝试使用 mod_proxy 和 mod_rewrite,但无济于事。如果我使用以下配置,我可以绕过端口 8000,并且它在端口 80 上可以正常播放音频流,但 http host dot domain dot com 只显示音频播放器,而不是整个 HTML 页面。我尝试了不同的组合并进行了谷歌搜索,但就是找不到原因。

我的问题是这是否是一个可行的解决方案。Apache 在 80 上,而 icecast 8000 通过同一端口代理?我可能需要两个 IP 吗?如果我使用两个 IP,那么正确的配置是什么。这是我的 Apache 虚拟主机配置。

ProxyRequests Off
ProxyPass / LINK1
ProxyPassReverse / LINK1
#RewriteEngine On
#RewriteRule ^/mount\.ogg$ LINK2 [P]

请注意,mount.ogg 是一个不存在的文件。它只是 icecast 的一个挂载点。

==>在此处发布链接(需要至少 10 点声誉)LINK1:http://host.domain.com:8000/mount.ogg 链接2:http://host.domain.com/mount.ogg

谢谢

答案1

我不想在我的唯一外部 IP 地址上在端口 80 上运行的 Icecast 和我的所有 Apache 虚拟主机(也在端口 80 上运行)之间做出选择。

我不想在防火墙上打开端口 8000,因为我希望所有用户都能访问 Icecast,即使是企业防火墙后面的用户。

因此,我设法在同一主机上运行监听端口 80 的 Apache 2.2 和监听端口 8000 的 Icecast 2.4.1。

我添加了一个新的虚拟主机 radio.domain.com(监听端口 80),它将 Icecast 流量路由到/从本地 Icecast 服务器(监听端口 8000):

<VirtualHost *:80>
    ServerName radio.domain.com
    ServerAdmin [email protected]
    ProxyPreserveHost On
    ProxyPass / http://localhost:8000/
    ProxyPassReverse / http://localhost:8000/
</VirtualHost>

然后我能够使用类似地址将 VLC/Winamp 等音频客户端连接到 Icecast 挂载点http://radio.domain.com/my_stream

但是,当连接到 Icecast 虚拟主机http://radio.domain.com/网页时,m3u 和 xspf 文件仍然会暴露http://radio.domain.com:8000/my_stream带有烦人的端口 8000 的 URL。然后下载这些文件的人无法连接到 Icecast 服务器,因为他们尝试连接到错误的端口。dir.xiph.org 上的 YP 更新也发生了同样的情况。

然后我下载了 Icecast 2.4.1 源代码,并对其进行了修改以添加新选项:

<exposed-port>80</exposed-port>

您可以在https://damiengarrido.wordpress.com/2015/03/22/icecast-reachable-behind-reverse-proxy/

如果需要的话,我可以在这里粘贴补丁。

答案2

首选方法是让 Icecast 直接监听端口 80,毕竟它是一个 HTTP 服务器。

由于多种原因,不建议使用反向代理。

  • 如果配置不正确,许多长连接将导致 Apache 崩溃
  • 一些旧功能(SOURCE、STATS)无法访问,只能在 2.4.1 和未来版本的 Icecast 中通过纯 HTTP 访问
  • YP 公共目录报告代码无法实现反向代理感知,这将破坏列表
  • 网络界面和生成的播放列表至少不容易正确

总而言之,如果您正在处理生产设置,并且是一名专业人士,并且确切知道自己在做什么,那么这是可能的,但并不容易。如果您只是随便想“哦,嘿,让我们像其他所有事情一样反向代理这个”,那么您会遇到一些麻烦。

获取一个额外的 IP,让 Icecast 监听该端口 80,很简单。

答案3

我能够找到使用两个虚拟主机的解决方案(部分)。对于可以访问端口 8000 的侦听器,配置与上述相同,只是没有 Proxy 指令。但在第一个虚拟主机的 HTML 页面中,我添加了一个链接,用于打开一个新窗口,该窗口指向我使用 ProxyReverse 的第二个虚拟主机。因此,第一个虚拟主机的 HTML 文件是

<audio controls>
    <source src="LINK1" type="audio/ogg">
</audio>
<a href="/"  onclick="window.open('LINK3', 'newwindow','width=300, height=100'); return false;"> No audio?</a>

其中 LINK3 链接到第二个虚拟主机,例如 host2 点域名点 com 正斜杠

然后,第二个虚拟主机的配置实际上执行了反向代理。

ProxyRequests Off
ProxyPass / LINK1
ProxyPassReverse / LINK1

也许我可以使用 1 像素框架并将链接指向那里,但我对这个解决方案也感到满意。

谢谢

答案4

我在合并运行在 Ubuntu 16.04 上的 apache2 的 443 端口上的自制 index.php 页面时遇到了同样的问题。我想使用自己的网页并传递音乐流的“脚本”(非 SSL)和当前正在播放的内容(也是非 SSL)。发生的情况是,一切都可以通过端口 80 运行,但是当我切换到 443 端口时,浏览器(尤其是 Chrome)会阻止我的“不安全脚本”,并且不会发出声音。

因此,在整个互联网上搜索并找到这个但不知道如何做之后,我终于明白了!

以下是我为感兴趣的人准备的:

  1. Windows 上的 Icecast 2.4.3 在端口 8080 上运行
  2. Ubuntu 16.04 LTS 在 Oracle VirtualBox 上运行,有近 20 个网站
  3. 我使用 MediaMonkey 4.1.16 和一个名为“edcast”的插件来连接到 Icecast

Apache2 配置文件:

<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName radio.domain.com
DocumentRoot /var/www/radio.domain.com

<Directory /var/www/radio.domain.com>
    Options Indexes FollowSymLinks MultiViews
    Order allow,deny
    allow from all
</Directory>

ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
SSLCertificateFile /etc/letsencrypt/live/radio.domain.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/radio.domain.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf

Options -Includes -ExecCGI
RewriteEngine On
RewriteCond %{THE_REQUEST} !HTTP/1.1$
RewriteRule .* - [F]

LimitRequestBody 512000
Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"
Header always set X-Frame-Options DENY

FileETag None
TraceEnable off
Header set X-XSS-Protection "1; mode=block"
Timeout 60

<Proxy *>
    Order deny,allow
    Allow from all
</Proxy>

ProxyRequests Off
ProxyPreserveHost On
SSLProxyEngine On
RequestHeader set Front-End-Https "On"

ProxyPass /stream http://192.168.1.2:8080/stream #IP and port of local computer on same network
ProxyPassReverse /stream http://192.168.1.2:8080/stream #IP and port of local computer on same network
ProxyPass /np.xsl http://192.168.1.2:8080/np.xsl #np.xsl is a file that I call using ajax from my index.php page to get the track currently playing
ProxyPassReverse /np.xsl http://192.168.1.2:8080/np.xsl #np.xsl is a file that I call using ajax from my index.php page to get the track currently playing

</VirtualHost>
</IfModule>

我的 np.xsl 文件(在 Icecast“web”目录中):

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output omit-xml-declaration="yes" method="text" indent="no" media-type="text/javascript" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/icestats">
parseMusic({
    <xsl:for-each select="source">"<xsl:value-of select="@mount"/>":{
        "server_name":"<xsl:value-of select="server_name"/>",
        "title":"<xsl:if test="artist"><xsl:value-of select="artist" /> - </xsl:if><xsl:value-of select="title" />",
        "bitrate":"<xsl:value-of select="bitrate" />"}
    <xsl:if test="position() != last()"><xsl:text>,</xsl:text>
    </xsl:if>
</xsl:for-each>});
</xsl:template>
</xsl:stylesheet>

我的index.php页面:

<!DOCTYPE html>
<html>
<head>
    <link rel="icon" href="favicon.ico" type="image/x-icon">
    <link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
    <title id="track-title"></title>
    <style>
        html{width:100%;}
        body{background-color:#bfbfbf; text-align:center; font-family:Helvetica;}
        #wrapper{position:absolute; max-width:550px; left:50%; transform:translate(-50%,0); -ms-transform:translate(-50%,0); -webkit-transform:translate(-50%,0); margin-right:-50%; text-align:center; box-shadow:1px 1px 20px 5px #4d4d4d;}
    </style>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
    <script>
    function updateTitle() {
    $.ajax({
            type: 'GET',
            url: 'https://radio.domain.com/np.xsl',
            jsonpCallback: 'parseMusic',
            dataType: 'jsonp'
    }).then(function (data) {
            var $track = $('#track-title').text(data['/stream'].title);
            var text = $track.text();
            $track.text(text.replace(" - MediaMonkey",""));
    }).fail(function (e) {
            console.log(e);
    }).always(function () {
            setTimeout(updateTitle, 5000);
    });
    }
    $(updateTitle);
    function updateTitle2() {
    $.ajax({
            type: 'GET',
            url: 'https://radio.domain.com/np.xsl',
            jsonpCallback: 'parseMusic',
            dataType: 'jsonp'
    }).then(function (data) {
            var $track = $('#track-title2').text(data['/stream'].title);
            var text = $track.text();
            $track.text(text.replace(" - MediaMonkey",""));
    }).fail(function (e) {
            console.log(e);
    }).always(function () {
            setTimeout(updateTitle2, 5000);
    });
    }
    $(updateTitle2);
    </script>
</head>
<body>
    <div id="wrapper">
    <h2>Live Radio</h2></br>
    <h4><span id="track-title2"></span></h4></br></br>
    <audio controls src="https://radio.domain.com/stream" type="audio/mp3"></audio><br></br>
    </div>
</body>
</html>

最后我的 icecast.xml 代码:

<icecast>
<location>Minneapolips, MN</location>
<admin>[email protected]</admin>
<hostname>radio.domain.com</hostname>
<limits>
    <clients>50</clients>
    <sources>1</sources>
    <queue-size>524288</queue-size>
    <client-timeout>30</client-timeout>
    <header-timeout>15</header-timeout>
    <source-timeout>10</source-timeout>
    <burst-on-connect>1</burst-on-connect>
    <burst-size>65535</burst-size>
</limits>
<authentication>
    <source-password>hackme</source-password>
    <relay-password>hackme</relay-password>
    <admin-user>admin</admin-user>
    <admin-password>hackmemore</admin-password>
</authentication>
<listen-socket>
    <port>8080</port>
    <shoutcast-mount>/stream</shoutcast-mount>
</listen-socket>
<http-headers>
    <header name="Access-Control-Allow-Origin" value="*" />
</http-headers>
<fileserve>1</fileserve>
<paths>
    <logdir>./log</logdir>
    <webroot>./web</webroot>
    <adminroot>./admin</adminroot>
    <alias source="/" destination="/status.xsl"/>
</paths>

<logging>
    <accesslog>access.log</accesslog>
    <errorlog>error.log</errorlog>
    <loglevel>4</loglevel> <!-- 4 Debug, 3 Info, 2 Warn, 1 Error -->
    <logsize>10000</logsize> <!-- Max size of a logfile -->
</logging>
</icecast>

它看起来像: 电台2017

电台2021

相关内容