Endpoints register but 401 unauthorized when calling?

Hi!

I have two rotary phones into HT801 ATAs. They register fine and I see them with “pjsip show endpoints”. For now they are on the same home LAN. They talk to a from-scratch asterisk server in the cloud (oracle free tier), version 22.1.0 built on ARM, Ubuntu 24.04.

When I call from one to the other, I get a busy signal.

Verbose logs in the asterisk CLI show a 401 Unauthorized. Here’s extension 42 calling extension 25:

<--- Received SIP request (1227 bytes) from UDP:76.22.6.154:5060 --->
INVITE sip:25@123.456.123.456 SIP/2.0
Via: SIP/2.0/UDP 192.168.0.2:5060;branch=z9hG4bK1097251453;rport
From: "Alice" <sip:42@123.456.123.456>;tag=945179225
To: <sip:25@123.456.123.456>
Call-ID: 1443926305-5060-8@BJC.BGI.D.DJ
CSeq: 60 INVITE
Contact: "Alice" <sip:42@192.168.0.2:5060>
Max-Forwards: 70
User-Agent: Grandstream HT801 1.0.57.1
Privacy: none
P-Preferred-Identity: "Alice" <sip:42@123.456.123.456>
P-Access-Network-Info: IEEE-EUI-48;eui-48-addr=40-3F-8C-72-D3-98
P-Emergency-Info: IEEE-EUI-48;eui-48-addr=00-0B-82-B6-44-5D
Supported: replaces, path, timer, eventlist
Allow: INVITE, ACK, OPTIONS, CANCEL, BYE, SUBSCRIBE, NOTIFY, INFO, REFER, UPDATE
Content-Type: application/sdp
Accept: application/sdp, application/dtmf-relay
Content-Length:   448

v=0
o=42 8000 8000 IN IP4 192.168.0.2
s=SIP Call
c=IN IP4 192.168.0.2
t=0 0
m=audio 5004 RTP/AVP 0 8 4 18 2 97 123 101
a=sendrecv
a=rtpmap:0 PCMU/8000
a=ptime:20
a=rtpmap:8 PCMA/8000
a=rtpmap:4 G723/8000
a=rtpmap:18 G729/8000
a=fmtp:18 annexb=no
a=rtpmap:2 G726-32/8000
a=rtpmap:97 iLBC/8000
a=fmtp:97 mode=20
a=rtpmap:123 opus/48000/2
a=fmtp:123 maxplaybackrate=16000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-16,32-36,54

<--- Transmitting SIP response (479 bytes) to UDP:76.22.6.154:5060 --->
SIP/2.0 401 Unauthorized
Via: SIP/2.0/UDP 192.168.0.2:5060;rport=5060;received=76.22.6.154;branch=z9hG4bK1097251453
Call-ID: 1443926305-5060-8@BJC.BGI.D.DJ
From: "Alice" <sip:42@123.456.123.456>;tag=945179225
To: <sip:25@123.456.123.456>;tag=z9hG4bK1097251453
CSeq: 60 INVITE
WWW-Authenticate: Digest realm="asterisk",nonce="1736299772/39bea68548ecc697e584f45f3ce3a8e8",opaque="07b482e26a006fb1",algorithm=MD5,qop="auth"
Server: Asterisk PBX 22.1.0
Content-Length:  0


<--- Received SIP request (284 bytes) from UDP:76.22.6.154:5060 --->
ACK sip:25@123.456.123.456 SIP/2.0
Via: SIP/2.0/UDP 192.168.0.2:5060;branch=z9hG4bK1097251453;rport
From: "Alice" <sip:42@123.456.123.456>;tag=945179225
To: <sip:25@123.456.123.456>;tag=z9hG4bK1097251453
Call-ID: 1443926305-5060-8@BJC.BGI.D.DJ
CSeq: 60 ACK
Content-Length: 0

My pjsip.conf and extensions.conf are hacks from the “make basic-pbx” command, and I’m so new to this that I assume some mistake in here is the reason (e.g. I don’t really understand all the dial plan stuff yet).

pjsip.conf:

[transport-udp-nat]
type = transport
protocol = udp
bind = 0.0.0.0


[mynet-endpoint](!)
type = endpoint
context = mynet
allow = all
trust_id_outbound = yes
device_state_busy_at = 1
dtmf_mode = rfc4733 ; works with HT801 rfc2833 setting

[auth-userpass](!)
type = auth
auth_type = userpass

[aor-single-reg](!)
type = aor
max_contacts = 1


[42](mynet-endpoint)
auth = 42
aors = 42
callerid = Alice <42>

[42](auth-userpass)
password = asdfasdf
username = 42

[42](aor-single-reg)
mailboxes = 42@example


[25](mynet-endpoint)
auth = 25
aors = 25
callerid = Bob <25>

[25](auth-userpass)
password = asdfasdf
username = 25

[25](aor-single-reg)
mailboxes = 25@example

extensions.conf:

[globals]
; General internal dialing options used in context Dial-Users.
; Only the timeout is defined here. See the Dial app documentation for
; additional options.
INTERNAL_DIAL_OPT=,30

[mynet]
; The order of includes here is important for matching the right extensions.
include = Dial-Users
include = Dialing-Errors

; Dial-Users handles calls to internal extensions.
; Calls coming into this context may be *external* or *internal* in origin.
[Dial-Users]
exten = _X,1,Verbose(1, "User ${CALLERID(num)} dialed ${EXTEN}.")
 same = n,Set(SAC_DIALED_EXTEN=${EXTEN})
 same = n,Gotoif($[${DEVICE_STATE(PJSIP/${EXTEN})} = BUSY]?dialed-BUSY,1:)
 same = n,Dial(PJSIP/${EXTEN}${INTERNAL_DIAL_OPT})
 same = n,Goto(dialed-${DIALSTATUS},1)

exten = dialed-NOANSWER,1,NoOp()
 same = n,Voicemail(${SAC_DIALED_EXTEN}@example,u)
 same = n,Hangup()

exten = dialed-BUSY,1,NoOp()
 same = n,Voicemail(${SAC_DIALED_EXTEN}@example,b)
 same = n,Hangup()

exten = dialed-CHANUNAVAIL,1,NoOp()
 same = n,Playback(pbx-invalid)
 same = n,Hangup()

exten = _dialed-.,1,Goto(dialed-NOANSWER,1)

exten = h,1,Hangup()

; Callers in the directory may dial 0 which will jump to the
; 'o' extension.
exten = o,1,Goto(42)

[Dialing-Errors]
; Handle any extensions dialed internally that don't otherwise exist.
; Comment out or remove this extension if you would rather have the calls
; ignored.
exten = _X.,1,Verbose(1, "User ${CALLERID(num)} dialed an invalid number.")
 same = n,Playback(pbx-invalid)
 same = n,Hangup()

pjsip show endpoints:


 Endpoint:  25/25                                                Not in use    0 of 1
     InAuth:  25/25
        Aor:  25                                                 1
      Contact:  25/sip:25@192.168.0.2:1024                 d8ccc83048 NonQual         nan

 Endpoint:  42/42                                                Not in use    0 of 1
     InAuth:  42/42
        Aor:  42                                                 1
      Contact:  42/sip:42@192.168.0.2:5060                 dbdaef7e18 NonQual         nan

Thanks for any pointers, or sharp blows to the head!

A 401 Unauthorized is normal. Asterisk is challenging for authentication. It is then up to the remote endpoint to re-send the INVITE with authentication.

Your log is incomplete (there are no errors in the part included), or the calling ATA doesn’t have a password configured. As the REGISTER seems to have worked, I tend to favour that the log is incomplete and the failure is not an authentication one.

This can cause various failures. In many cases the resulting over long request gets truncated, and there are some versions of Asterisk which cannot correctly handle offers for certain special codecs included in the full list.

The destination number is two digits but your dialplan is either incomplete (there is no Dialing-Errors context), or only accepts single digit numbers. Please investigate the use of “.” and “!” in dialplan extension patterns.

You probably want to handle CONGESTION, as well.

Thanks for the replies! I will make an extensions.conf from scratch and do my homework on that syntax. Thought I would get away with cribbing the fancy one. :slight_smile:

@jcolp – I was aware of the expected 401 with registration, but given that the INVITE was not re-sent (judging by the logs?) I thought it might indicate something weird in the INVITE context. Do these logs imply that my HT801 is not behaving properly for some reason?

@david551 – yeah, the logs seemed weird to me, too (even as a newbie). I did set the password in the HT801, and given that the registration worked, I wonder why the logs are incomplete? This is definitely everything that comes out on the CLI. Perhaps there is some logging I failed to enable? It seems like the HT801 gets the 401, sends an ACK, and just stops?

I will recreate a from-scratch extensions.conf (with knowledge, this time) so I will take your points to heart on allow= and CONGESTION and so forth. However, you mentioned “there is no Dialing-Errors context” – isn’t there? I thought it was at the end of the extensions.conf I posted above?

It would be the responsibility of the HT801 to re-send it, so if it isn’t then it is not behaving as expected. Why that may be the case I do not know.

Hmm, so I believe I have my extensions.conf sorted out, but I’m still having a problem:

I seem to be having the same issue as user @cbfs here: INVITE from extension being dropped - #6 by cbfs

…as @david551 noted, my log stops after the “ACK” from the endpoint, which seems truncated/incomplete, but if I tcpdump the interface I can see that my Grandstream HT801 is in fact sending INVITEs (with authorization headers included) after the 401, but they are not showing up at asterisk (or at least it is not logging them.) They also seem to be getting truncated or corrupted somehow.

I did tcpdump -w /tmp/my.cap -n -XX 'udp port 5060'

If I view the my.cap file in a text viewer I can see:
→ INVITE
← 401
→ ACK
→ INVITE (with auth)
→ INVITE (with auth)
→ INVITE (with auth)

…but the asterisk console only shows up to the ACK. If I open my.cap in wireshark, it shows the first invite as a UDP SIP, but the final three INVITES show as “Fragmented IP protocol”:



In the other thread, they mention that tcpdump shows info before iptables, and asterisk is of course after iptables, but I don’t think I have anything going on in iptables:

# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

I will note that I had trouble with registration before, so I installed iptables and added some rules in there to open up port 5060, etc, which seemed to help, but no longer seems to be necessary and those rules are no longer present (and I have flushed, rebooted, etc.)

So I get the impression that either some mysterious firewall layer is preventing things from getting to asterisk, or asterisk isn’t accepting the subsequent INVITEs for some reason, or they are getting corrupted somehow.

When I look at the raw tcpdump capture file, it appears as if the later INVITEs are getting cut off. Here for example are the last few lines (viewed via “less” on the CLI), leading to the next INVITE (I’m leaving the binary junk in there, but it seems like it gets to “tel” and stops, where in the “good” INVITE that line is “a=rtpmap:101 telephone-event/8000” and there are more lines after it):

...
a=fmtp:123 maxplaybackrate=16000
a=rtpmap:9 G722/8000
a=rtpmap:101 tel߅g�����_
                        �E�Kv 5�=L�
���02INVITE sip:42@146.235.204.128 SIP/2.0
Via: SIP/2.0/UDP 192.168.0.2:1024;branch=z9hG4bK679466292;rport
...

…any ideas where this might be going wrong? Does it seem more like an OS/network layer issue at this point?

Update: I did strace -p 822 -f -e trace=network -s 10000 (where 822 was the PID of asterisk) and it confirmed that asterisk is not seeing the subsequent (possibly corrupt) INVITEs at all, so this is something happening on an OS level, I assume.

Any idea where to look? This is a generic minimal install of Oracle’s Ubuntu 24.04.1 on the free tier oracle ARM cloud server…

Hmm, yeah, so the problem seems to be that the oracle cloud network is not transmitting fragmented UDP datagrams. The first INVITE is small enough to fit in a single fragment so it gets through. The INVITE with the authorization inside is too large, gets fragmented, so only the first IP fragment comes through, so the datagram is never completed, so the OS network layer never has complete data to give to asterisk. I’m currently trying to figure out how to tweak the firewall rules to fix this but I’m at a loss so far. Any insight is welcome!

Aha – at least with the Oracle cloud, if you only open up the important ports for UDP (I was opening 5060-5061) it doesn’t work, because for a fragment UDP datagram only the first fragment contains the destination port, so the subsequent fragments just get blocked. You have to set your ingress UDP firewall rule to allow “All” ports, then it works (well, it works as expected – I still have issues with my asterisk that I can now work on without this issue confusing things. :slight_smile: )

This is why the server network layer was only seeing the beginning of the authorized INVITES, and why asterisk never saw them at all.