[Icecast-dev] Micro Guide to Understanding Icecast 2.5.x authentication (For Icecast 2.5 beta 3)

Philipp Schafft phschafft at de.loewenfelsen.net
Fri Nov 9 11:10:22 UTC 2018


Good morning,

as there has been some confusion I thought it might be best to write
some little "Micro Guide" for Icecast 2.5.x's authentication subsystem.
This E-Mail refers to not yet released version 2.5 beta 3 (to be
released soon).

!!!  /!\  !!!
If you run Icecast 2.4.x (stable) this E-Mail is not relevant to you!
!!!  /!\  !!!


Overview
        Icecast 2.5.x changed the authentication system very much since
        Icecast 2.4.x. But good news first: Icecast 2.5.x can read
        Icecast 2.4.x config files and will behave correctly.
        
        The new system works by a set of rules. Rules are tried from top
        to bottom. The first one that matches wins. When a rule matches
        a set of access control parameters are set.
        
        Rules can be defined by (and tried in this order):
              * listen sockets (<listen-socket>),
              * normal mounts (<mount type="normal">),
              * default mounts (<mount type="default">),
              * the global list (<icecast>).
        
        Each of those blocks can contain a <authentication> subtag.
        (Note: It must not set a type="", otherwise it will be
        interpreted as Icecast 2.4.x config).
        
        Each such <authentication> can contain a number of <role> tags.
        Each <role> tag defines a rule.
        
        A <role> tag can include <option>, and <http-headers> tags.
        <option> tags are used to define additional options for the used
        backend the same way as they did in 2.4.x.
        
        Examples can be found at the end of this E-Mail.

Defining a role
        A <role> represents a rule in the system. The servers will try
        all related <role>s when a client connects in from top to
        bottom.
        
        A role may contain filters on parameters of the client. Such as
        the request method. By default no filters are used.
        
        When the role's filters match the request (or no filters are
        set) the configured backend is asked. Such backends include
        static username/password sets or more empowered backends such as
        the URL auth backend.
        
        The will report a positive (success) or negative match (access
        deny) or no-match (the next rule is tried).
        
        When a role returned a negative match access to the requested
        resource is denied.
        
        When a positive match is returned the given access control rules
        are applied.

Defining access control rules
        Access control rules can be defined as part of the <role> tag.
        
        There currently are the following access parameters that can be
        set:
              * which HTTP methods are allowed (such as GET or PUT)
                (allow-method, deny-method; default: allow only GET and
                OPTIONS),
              * which admin/ commands are allowed (allow-admin,
                deny-admin; default: allow only buildm3u (playlist
                generation)),
              * if web/ access (that is the status page and the actual
                streams) is allowed (allow-web, deny-web; default: allow
                web access),
              * how many simultaneous connections can be made by a user
                (connections-per-user; default: unlimited connections),
              * how long a listener might listen to a stream before
                being automatically disconnected (connection-duration;
                default: unlimited time).

Examples:
        Consider the following global <authentication> block:
        <authentication>
                <role type="static" allow-all="*" >
                        <option name="username" value="admin" />
                        <option name="password" value="hackme" />
                </role>
                <role type="static" allow-web="*" deny-admin="*" >
                        <option name="username" value="listener" />
                        <option name="password" value="salad" />
                </role>
                <role type="anonymous" deny-all="*" />
        </authentication>
        
        This first checks for a user with the username "admin" and the
        password "hackme". If the client sent those credentials it
        allowd to have full access (allow-all="*").
        
        Then the server checks for the user with username "listener" and
        password "salad". If the client sent those credentials to the
        server it is allowed web access (and listening to streams)
        (allow-web="*") but no admin access (deny-admin="*").
        
        If no of the above rules match the last rule matches and forbids
        all access (deny-all="*").
        
        
        Now let's consider the following additional block:
        <mount type="normal">
                <mount-name>/example1.ogg</mount-name>
                <authentication>
                        <role type="static" allow-web="*">
                                <option name="username"
                                value="friend" />
                                <option name="password" value="wine" />
                        </role>
                </authentication>
        </mount>
        
        This <mount> block configures the mountpoint "/example1.ogg". It
        contains a <authentication> with a single <role>.
        
        Let's see what happens:
        
        Now if a client connects to this specific mount point it is
        first checked if it's our friend "friend" with the password
        "wine". If it's our friend we allow listen him to listen to the
        stream as well.
        
        Here no rule for admin access has been defined, so the default
        value is used: Allow playlist generation only.
        
        If the client is not our friend, the rules from the global
        section are tried.
        
        
        Our last example will disable admin access on a given listen
        socket (e.g. for restricting it to an internal interface). We do
        this by applying a filter.
        
        Consider the following block:
        <listen-socket>
                <bind-address>192.0.2.137</bind-address>
                <port>8000</port>
                <authentication>
                        <role type="anonymous" match-admin="*"
                        nomatch-web="*" deny-all="*" />
                </authentication>
        </listen-socket>
        
        In this example all clients that request admin any admin
        commands (match-admin="*") but no clients requesting web/
        resources (nomatch-web="*") are rejected (deny-all="*").

Conclusion and looking forward
        The new authentication subsystem is very powerful and can be
        used for complex setups. However it requires more understanding
        of rule based access control.
        
        The new and the old style configs can freely be mixed to enable
        both a smooth transition as well as make simple setups keep
        simple (e.g. by using the old style <source-password> tag).
        
        We currently work on ways to make the config a bit simpler and
        also to document things better. This E-Mail is a first part of
        this.
        
        There are a lot more options that have not been covered in this
        E-Mail such as more complex matching setups or backend based
        client rewrites.
        
        There are also some more ideas for the future features such as
        better integration of <resource>[0][1] or optimizations to keep
        load off the actual backend by handling challenge requests
        internally.

I'm happy to answer all questions and looking forward to any feedback!

With best regards,


[0] Previously known as <alias>. Has been improved a lot!
[1] Maybe worth another E-Mail? Let me know if there is interest.

-- 
Philipp Schafft (CEO/Geschäftsführer) 
Telephon: +49.3535 490 17 92

Löwenfelsen UG (haftungsbeschränkt)     Registration number:
Bickinger Straße 21                     HRB 12308 CB
04916 Herzberg (Elster)                 VATIN/USt-ID:
Germany                                 DE305133015
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: This is a digitally signed message part
URL: <http://lists.xiph.org/pipermail/icecast-dev/attachments/20181109/8a35ec55/attachment.sig>


More information about the Icecast-dev mailing list