SQL Server binds a VPN address that is not there at boot
Walk a failed SQL Server bind from the startup log to the effective listener, then give clients a stable private address instead of a VPN pool address.
Read a SQL Server log line about a failed bind while the service is still running, and you have found a boot-order dependency rather than a crash. That combination is the clue: the engine started before the address it was told to listen on existed on the machine. A VPN adapter that comes up after sign-in is a poor prerequisite for an unattended database service, so walk the failure in the order the engine sees it.
Start at the startup log, not at the client
Open the instance error log and read the entries around the network initialization, not just the last line. The engine reports which addresses it tried and which protocols it enabled, and that record is from before any client connected. Now look at what exists on the host right now. If the interface that owns the configured address appears only after a user signs in and starts a client, the address was absent at boot and the bind failure is fully explained.
Get-NetIPAddress -AddressFamily IPv4 | Select-Object InterfaceAlias, IPAddress, PrefixOrigin
Get-Content 'C:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\LOG\ERRORLOG' -Tail 40
Adjust the instance path to your installation, and read the interface list before drawing conclusions. An address that exists but is owned by the wrong adapter is a different problem from an address that does not exist yet.
Walk the bind order the engine actually follows
The engine reads its listener configuration, then asks the operating system to bind. If the address is not local at that moment, the bind fails for that address while the rest of the instance may continue normally. That is why other protocols or other addresses can still work, and why "SQL Server is down" is the wrong summary. Preserve the exact endpoint from the log: address, port and protocol, because the fix depends on which of the three is wrong.
Restarting the service after the adapter appears will usually make the listener succeed, which is exactly the trap. It proves the dependency rather than removing it, and it breaks every connected user each time the tunnel reconnects.
Read the listener the way the engine reads it
In SQL Server Configuration Manager, open the instance's TCP/IP properties and note the Listen All setting before editing individual addresses. When Listen All is Yes, the per-address Enabled values are ignored, so editing them changes nothing that the listener uses. Record three things in order: the address you intend to serve, the port, and whether the listener is meant to cover all addresses or only one. Then apply the change through the supported restart procedure and read the next startup log to confirm the engine bound what you asked for.
Listening on every address is not access control. If a broad listener is genuinely required, each reachable interface needs its own firewall and database authorization decision, including any interface that faces the internet.
Give the client a stable destination
The client does not need the database host to wear a pool address. A routed design works with the server listening on its stable private address while the VPN gateway forwards the client's traffic to it and carries the reply back.
Test-NetConnection -ComputerName 10.80.0.15 -Port 1433
tracert -d 10.80.0.15
If the client reaches 10.80.0.15, the path is proven and the database only has to authorize that client. If it does not, fix routing and DNS before touching the listener again, because a bind problem on the server was never the reason a client cannot find it. Adding a fake pool address to the server, or a second default gateway to make the listener happy, creates a new network problem on top of the old one. Keep the server's addressing static and let the tunnel carry clients to it.
Verify the endpoint the client used
Finish with an application-level check rather than a port test. Connect from the client with the account the application uses and read the server-side connection details, which show the local address your session landed on.
sqlcmd -S tcp:10.80.0.15,1433 -Q "SELECT local_net_address, local_tcp_port FROM sys.dm_exec_connections WHERE session_id = @@SPID"
Compare that address with the listener you configured. A mismatch means a second listener or a name resolving somewhere unexpected, and both are worth knowing before the next reboot tests your fix for you. Then reboot the host with no user signed in and confirm the bind succeeds. That single test is the difference between a repaired listener and a workaround that fails on the next patch night.