-
Notifications
You must be signed in to change notification settings - Fork 1.5k
[Bug] Fixing Bastion tunnel establishment issue #8916
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
When running az network bastion tunnel inside WSL2, the command hangs for ~60 seconds before opening the tunnel. This is caused by a port availability check using socket.connect_ex(('', port)), which resolves to 0.0.0.0 and causes a timeout in WSL.
See examples
```
strace -f -tt python3 -c "import socket; import time; s=socket.socket(); s.settimeout(5); t=time.time(); r=s.connect_ex(('', 44444)); print(f'Result: {r}, Time: {time.time()-t:.2f}s')"
```
Output:
```
00:03:27.779861 socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 3 00:03:27.780376 ioctl(3, FIONBIO, [1]) = 0 00:03:27.780642 connect(3, {sa_family=AF_INET, sin_port=htons(44444), sin_addr=inet_addr("0.0.0.0")}, 16) = -1 EINPROGRESS (Operation now in progress) 00:03:27.781179 poll([{fd=3, events=POLLOUT|POLLERR}], 1, 5000) = 0 (Timeout) 00:03:32.787945 write(1, "Result: 11, Time: 5.01s\n", 24Result: 11, Time: 5.01s ) = 24 00:03:32.788904 rt_sigaction(SIGINT, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER|SA_ONSTACK, sa_restorer=0x7db0bc045330}, {sa_handler=0x6e7170, sa_mask=[], sa_flags=SA_RESTORER|SA_ONSTACK, sa_restorer=0x7db0bc045330}, 8) = 0 00:03:32.792342 getsockname(3, {sa_family=AF_INET, sin_port=htons(47226), sin_addr=inet_addr("127.0.0.1")}, [16]) = 0
```
vs
```
strace -f -tt python3 -c "import socket; import time; s=socket.socket(); s.settimeout(5); t=time.time(); r=s.connect_ex(('127.0.0.1', 44444)); print(f'Result: {r}, Time: {time.time()-t:.2f}s')"
```
Output:
```
00:03:32.793450 getpeername(3, 0x7ffde75bdb70, [16]) = -1 ENOTCONN (Transport endpoint is not connected) 00:03:32.794071 close(3) = 0 00:03:32.800493 munmap(0x7db0bc531000, 16384) = 0 00:03:32.801438 exit_group(0) = ? 00:03:32.803541 +++ exited with 0 +++
```
️✔️Azure CLI Extensions Breaking Change Test
|
|
Hi @sabbour, |
|
Thank you for your contribution! We will review the pull request and get back to you soon. |
|
The git hooks are available for azure-cli and azure-cli-extensions repos. They could help you run required checks before creating the PR. Please sync the latest code with latest dev branch (for azure-cli) or main branch (for azure-cli-extensions). pip install azdev --upgrade
azdev setup -c <your azure-cli repo path> -r <your azure-cli-extensions repo path>
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes the port availability check in the Bastion tunnel command by using the explicit local address instead of binding to all interfaces, which resolves a 60-second hang in WSL2.
- Change socket.connect_ex to use
self.local_addrrather than'' - Retains existing logging, but aligns connection attempt with the provided local address
Comments suppressed due to low confidence (1)
src/bastion/azext_bastion/tunnel.py:73
- [nitpick] Add or update unit tests for
is_port_opento cover cases with explicitlocal_addr, ensuring correct behavior on different environments (e.g., WSL2 vs. Linux).
if sock.connect_ex((self.local_addr, self.local_port)) == 0:
CodeGen Tools Feedback CollectionThank you for using our CodeGen tool. We value your feedback, and we would like to know how we can improve our product. Please take a few minutes to fill our codegen survey |
|
The logic was inverted. `sock.connect_ex` returns 0 if the connection is successful, hence when the port is open.
|
/azp run |
|
Azure Pipelines successfully started running 2 pipeline(s). |
|
For the failed integration test, I think it's caused by dependency bump in official azure-cli (default API version has changed from
|
|
@FumingZhang I've pushed the revert. |
|
/azp run |
|
Azure Pipelines successfully started running 2 pipeline(s). |
|
Unfortunately, the integration test has failed again. I attempted to re-run it locally to regenerate the recording file, but that also failed. As a temporary workaround, you can manually update the existing recording file. Based on the error message, you may need to modify the following section to
|
|
Ok I will try to do that. Thank you. |
Attempting to fix the test case
|
/azp run |
|
Commenter does not have sufficient privileges for PR 8916 in repo Azure/azure-cli-extensions |
|
/azp run |
|
Azure Pipelines successfully started running 2 pipeline(s). |
|
replaced by #8952 |
When running
az network bastion tunnelinside WSL2, the command hangs for 2 minutes and 15 seconds before opening the tunnel.Attached is the
stracelog: bastion-tunnel-strace.logUpon investigation using
strace, the code is attempting to connect to0.0.0.0:{port}to validate if the port is in use or not, which is an invalid destination address. 0.0.0.0 is not a routable IP address representing "any address" or "no specific address" and cannot be used as a connection target. This is the documented behavior in the Python socket library: https://docs.python.org/3/library/socket.htmlSee examples executing the
connect_exfunction directly:Output:
vs
Output:
This checklist is used to make sure that common guidelines for a pull request are followed.
Related command
az network bastion tunnel
General Guidelines
azdev style <YOUR_EXT>locally? (pip install azdevrequired)python scripts/ci/test_index.py -qlocally? (pip install wheel==0.30.0required)For new extensions:
About Extension Publish
There is a pipeline to automatically build, upload and publish extension wheels.
Once your pull request is merged into main branch, a new pull request will be created to update
src/index.jsonautomatically.You only need to update the version information in file setup.py and historical information in file HISTORY.rst in your PR but do not modify
src/index.json.