Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/sip-allowed-addresses-source-only.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"github.com/livekit/protocol": patch
"@livekit/protocol": patch
---

Match an inbound trunk's allowed_addresses against the source address only
12 changes: 9 additions & 3 deletions sip/sip.go
Original file line number Diff line number Diff line change
Expand Up @@ -443,17 +443,23 @@ func matchAddrMask(ip netip.Addr, mask string) bool {
return pref.Contains(ip)
}

func matchAddrMasks(addr string, host string, masks []string) bool {
// matchAddrMasks reports whether the call's source address is inside one of the masks. Only the
// transport address is consulted: a From host is written by the caller, so matching a mask against it
// would let any INVITE satisfy the allowlist by claiming the right host. A hostname entry therefore
// matches nothing, and a list made only of hostnames admits no call.
func matchAddrMasks(addr string, masks []string) bool {
ip, err := netip.ParseAddr(addr)
if err != nil {
return true
}
// A dual-stack listener reports IPv4 peers as ::ffff:a.b.c.d; the masks are written as IPv4.
ip = ip.Unmap()
masks = filterInvalidAddrMasks(masks)
if len(masks) == 0 {
return true
}
for _, mask := range masks {
if mask == host || matchAddrMask(ip, mask) {
if matchAddrMask(ip, mask) {
return true
}
}
Expand Down Expand Up @@ -543,7 +549,7 @@ func MatchTrunkDetailed(it iters.Iter[*livekit.SIPInboundTrunkInfo], call *rpc.S
continue
}
}
if !matchAddrMasks(call.SourceIp, call.From.Host, tr.AllowedAddresses) {
if !matchAddrMasks(call.SourceIp, tr.AllowedAddresses) {
if !opt.Filtered(tr, TrunkFilteredSourceAddressDisallowed) {
continue
}
Expand Down
63 changes: 53 additions & 10 deletions sip/sip_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,13 +205,44 @@ var trunkCases = []struct {
exp: -1,
},
{
name: "inbound with host mask",
name: "inbound with host mask is not matched by the From host",
trunks: []*livekit.SIPTrunkInfo{
{SipTrunkId: "bbb", OutboundNumber: sipNumber2, InboundAddresses: []string{
"10.10.10.0/24",
"sip.example.com",
}},
},
exp: -1,
},
{
name: "inbound with address mask is not matched by a From host naming that address",
trunks: []*livekit.SIPTrunkInfo{
{SipTrunkId: "bbb", OutboundNumber: sipNumber2, InboundAddresses: []string{
"192.76.120.10",
}},
},
host: "192.76.120.10",
exp: -1,
},
{
name: "inbound with address mask is matched by an IPv4-mapped source address",
trunks: []*livekit.SIPTrunkInfo{
{SipTrunkId: "bbb", OutboundNumber: sipNumber2, InboundAddresses: []string{
"192.76.120.10",
}},
},
src: "::ffff:192.76.120.10",
exp: 0,
},
{
name: "inbound with host mask is matched by the source address",
trunks: []*livekit.SIPTrunkInfo{
{SipTrunkId: "bbb", OutboundNumber: sipNumber2, InboundAddresses: []string{
"10.10.10.0/24",
"sip.example.com",
}},
},
src: "10.10.10.7",
exp: 0,
},
{
Expand Down Expand Up @@ -1192,7 +1223,6 @@ func TestMatchMasks(t *testing.T) {
cases := []struct {
name string
addr string
host string
masks []string
exp bool
}{
Expand Down Expand Up @@ -1235,18 +1265,32 @@ func TestMatchMasks(t *testing.T) {
exp: false,
},
{
name: "hostname",
name: "address mask is not the From host",
addr: "1.1.1.1",
masks: []string{
"192.76.120.10",
},
exp: false,
},
{
name: "mapped address",
addr: "::ffff:192.168.0.10",
masks: []string{
"192.168.0.0/24",
},
exp: true,
},
{
name: "hostname matches nothing",
addr: "192.168.0.10",
host: "sip.example.com",
masks: []string{
"sip.example.com",
},
exp: true,
exp: false,
},
{
name: "invalid hostname",
addr: "192.168.0.10",
host: "sip.example.com",
masks: []string{
"some.domain",
},
Expand All @@ -1271,20 +1315,19 @@ func TestMatchMasks(t *testing.T) {
exp: false,
},
{
name: "domain name",
name: "domain name beside a wrong range",
addr: "192.168.0.10",
host: "sip.example.com",
masks: []string{
"some.domain",
"192.168.1.0/24",
"sip.example.com",
},
exp: true,
exp: false,
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
got := matchAddrMasks(c.addr, c.host, c.masks)
got := matchAddrMasks(c.addr, c.masks)
require.Equal(t, c.exp, got)
})
}
Expand Down
Loading