Why not two external IP addresses for Asterisk?

One limitation of Asterisk has always been that if it’s behind NAT, it can know only of one external IP address, which it puts in the SIP messages that leave your internal network (with calls to your voice service provider e.g.).

Now a lot of people are using more than one ISP and have e.g. two internet connections for fail over.

In that case the solution with Asterisk is to instead of a specific external IP address, to use an external hostname, which gets updated after a fail over event.
This is however an inferior solution, as the hostname might not get updated immediately and then you won’t be able to make outbound calls for a while.

Has the Asterisk team ever considered to do something about this problem?

It would be great if you could specify several external IP addresses.
So e.g. when sending a SIP packet to public IP address A (sip provider abc), then put external IP address 1 in the sip header. When sending to public IP address B, then use external IP address 2.

Or let the user set an external IP address in the endpoint configuration in sip.conf (or pjsip.conf), overriding the general settings on a case by case scenario. (So a different external IP for each trunk).

The user would also configure static routes on the linux server to route the traffic accordingly if needed.

The correct way of handling multihoming is by obtaining an autonomous system number and using border gateway protocol. That way it won’t matter which IP address is used.

If you are fudging multihoming, you could put Asterisk on the public side of the NAT boundary, or you could run multiple instances of Asterisk, one for each ISP, and using local trunks between them.

Are several external IP addresses possible with pjsip?

I just read a thread where @ambiorixg12 suggested that you could use the options external_media_address and external_signaling_address independently for each SIP peer configuration.

So does that override what’s in the default context in pjsip, and whatever IP you have as external_signaling_address for each peer will be put into the sip messages?

Not really, unless you configure different transports and use them. There’s the “media_address” option per-endpoint but I don’t think it currently resolves the hostname or regularly updates it. There’s no per-endpoint option for signaling.

It would be very useful if it were. That would make it easier to deal with environments with several WAN sources.
You could have one trunk go out over one ISP, another trunk out another ISP.
So far we have to use proxies or DDNS to deal with this.

Did you guys at Digium ever consider implementing something like this?

No, and it’s not something that anyone has ever really asked for. I think it’s come up maybe 3 times that I can remember.

I see it come up fairly often on the FreePBX forum.

There is still the second transport option in PJSIP. Provided they are on different ports and set explicitly on the endpoint/other configuration then they can have different external addresses.

I’m fairly sure it has come up more than three times, but it arises from abusing (TCP/)IP to avoid the costs of doing it properly.

The way that the internet is designed to work is that, if you have multiple interfaces connected to the internet, they are all equally good addresses for your system, and traffic addressed to one of them will arrive by whichever interface is closest, in network terms. To make this work, you need an autonomous system number and you need to use routed, or similar, to operate the Border Gateway Protocol.

At least at one time, unless you had a large enough block of addresses, it wasn’t actually possible get BGP routes to propagate globally. Also, a lot of people seeking multi-homing are unaware that it even exists, because they are using internet connectively products that are only one step above the consumer level.

1 Like

Yeah, 3 times is just what I remember - my gist being that it’s not something everyone is screaming for. If it shows up enough then it has a better chance of being implemented in some fashion.

In our environment we have several routers connected to the internet using different ISPs.

We wanted to sign up with different SIP trunking providers, registering to each one over a different internet link, using static routes on our Linux servers.
With Asterisk this is impossible, as it only knows about one external IP address which it puts in the SIP messages. So you can register your trunks over different internet links to your VSP, but the SIP messages will contain the wrong external IP, screwing up the audio path.

What function does the external_signaling_address option in your peer details have exactly?

I will take a look at the second transport option that @jcolp suggested,
Is there any documentation available on it?

The external_signaling_address option can only be set on a transport. Combined with local_net it controls the external address to place in the signaling.

There is no explicit documentation about multiple transports. You just define multiple of them (using different ports) and they exist. They can each have different external_* options. You then specify which one to use on a per-endpoint basis.

What happens at the system level to ensure they go out the right way is outside the scope of Asterisk.

Yes I forgot to specify you need to configure, different transport section and then use them

Sorry to resurrect an old thread, but I find myself dealing with this same issue at the moment. And, I could really use some guidance. I’m way too small to do it the “right way” with an ASN and BGP, so I’m trying to find a work around.

My plan is to create a separate PJSIP transport for each of my external IPs. My question is: how can I make asterisk handle these transports intelligently?

For example, suppose ISP1 goes down. I would like my trunks to automatically use ISP2 instead. Or, asterisk could even load balance over both ISPs simultaneously. Would it make sense to configure 2 copies of each trunk (one configured with the transport for ISP1 and one for ISP2)? Then, asterisk could try to use either copy when making and receiving calls.

I read this post about how PJSIP selects a transport, but honestly, I had a hard time understanding how it would apply in this situation.

It doesn’t do load balancing and it doesn’t know if something is down. There is nothing built in to do this.

Wow, thanks for the super fast reply. :slight_smile:

Ok, so I can understand this better, if I had a configuration kind of like the following, and the ISP that I get 5.5.5.5 from is currently down. What happens?

I assuming incoming calls from the ISP that I get 6.6.6.6 from would still come through and be matched to the appropriate trunk. But, what about outgoing? Will they all attempt to use mytrunk-1 and fail because the transport assigned to that trunk isn’t working? Am I just thinking about this too simply?

Sorry for the basic questions. I’m still trying to wrap my head around this.

[system-internet-tls-1]
type=transport
protocol=tls
bind=5.5.5.5:5061
external_signaling_address=isp1.example.com
external_media_address=isp1.example.com

[system-internet-tls-2]
type=transport
protocol=tls
bind=6.6.6.6:5061
external_signaling_address=isp2.example.com
external_media_address=isp2.example.com

[mytrunk-1]
type=endpoint
context=from-external
outbound_auth=mytrunk
aors=mytrunk
transport=system-internet-tls-1

[mytrunk-2]
type=endpoint
context=from-external
outbound_auth=mytrunk
aors=mytrunk
transport=system-internet-tls-2

For outgoing you would have to specify which endpoint is used yourself, and as transport is specified explicitly it would use the explicit transport (no matter if it is up or down).

Ok, I think I’m tracking with you. Of course, if I didn’t explicitly specify the transport, and I just configured one trunk and made both transports available?

As I understand the documentation, the following logic would apply:

An already open connection to the resolved IP address and port is searched for. If the connection exists it is reused for the request. If no connection exists the first transport matching the transport type and address family as configured in pjsip.conf is chosen. It is instructed to establish a new connection to the resolved IP address and port.

Which would mean that whatever trunk is listed first in the config would always be chosen. So, I think I’m finally understanding why my initial plan won’t work. Thanks for explaining that.

That said, could I use something like the techniques described in these posts to achieve my end goal? Those are for chan_sip, but I don’t see why they wouldn’t work with chan_pjsip.

So, I would have everything setup like the config above and in my dialplan it first tries mytrunk-1 and then mytrunk-2 if mytrunk-1 doesn’t work. Could that work?

It depends on how long of a timeout is allowed, it will “failover” in the sense it will continue in the dialplan.

Gotcha, that makes sense. So, a configuration like the one above could theoretically work. It would just have some issues with downtime due to qualify frequency and timeouts. Correct?

Do you know of a better solution for multiple ISPs/external addresses that doesn’t involve BGP and my own block of static IPs? Would @david551’s proposed solution be more elegant/reliable?

The issue I see there is all of my phone endpoints. Would they need to register with both instances or just one? If both, how would they choose which one to use? If one, what happens if the one they are registered with is down?