Disclaimer: this is not a duplicate!
I'm using requests library, monkey patched under GAE standard environment and everything works flawlessly, except the times when I'm adding the extra proxy
argument to the request call. This proxy thing implies tunneling and socket operations which are disabled by default by the standard configuration of both development and deploy environments:
NotImplementedError: HTTP CONNECT Tunnelling is not supported
https://pastebin.com/YDsG9we7
Nice, so we need to enable real sockets support under our GAE platform, therefore adding:
env_variables:
GAE_USE_SOCKETS_HTTPLIB : "True"
And even without doing the requests toolbelt monkey patch (not using urlfetch at all), we get a permission denied: https://pastebin.com/ifBFKi3K
This usually happens when the sandbox thinks that you're accessing a forbidden server location or port, but the proxy is fully functional and guess what, I've tested the very same code (without any added/removed functionality due to development or deploy server as current environment) and it works just as expected on the deploy, without any kind of Permission denied
errors, by making the request completely successfull (if we try without httplib sockets enabled, we still get that Tunnelling is not supported
error under both scenarios and this is the expected behavior).
Now, I've got a working solution on the deploy (which is what it really counts), but this is not enough for me, I just want to test these requests through proxies under my development server and environment too, so what I've tried to do is the following:
- let's import our own standard sockets library by applying these: "ImportError: No module named _ssl" with dev_appserver.py from Google App Engine
- can't monkey patch the sandbox.py file for white-listing
_sockets
and_ssl
etc., no problem, I've hard-patched that directly on disk into the original file - replacing into memory the default sockets, httplib imports etc. with the standard pythonic ones
- ISSUE:
ValueError: select only supported on socket objects.
https://pastebin.com/gHFM6QiF ; and this is somehow expected to happen, as the expected socket object is different from the expected one due to the standardsockets
import but GAE's ownselect
(and by removing select from the interpreter's memory will just cause more issues or not work at all), so I want to replace theselect
module (which is a built-in) too with the standard pythonic one, how can I do that?
- can't monkey patch the sandbox.py file for white-listing
Nevermind...
Is there any method through which this nightmare will end and still using the standard environment? If it works on the deploy server without any patches at all, why shouldn't also work with the dev_appserver tool too?
I just don't want to do any more patches, I just want to get past that Permission denied
error which is not thrown under the remote deploy server, using the very same code logic, no matter if we use requests, urlfetch, httplib, sockets etc. (just the proxy's required tunneling thing).
Digged-in the issue further and seems to be into this file:
platform/google_appengine/google/appengine/api/remote_socket/_remote_socket_stub.py which has some mocked socket pairs of (level, option) found in constant _MOCK_SOCKET_OPTIONS
which is missing the (1, 3) pair and by this I mean one of the product of levels and options below (I guess the asterisk is the desired value):
Levels (value: 1):
- SOCKET_TCP_NODELAY
- SOCKET_IP_TOS
- SOCKET_SOL_SOCKET *
- SOCKET_SO_DEBUG
Options (value: 3):
- SOCKET_IP_HDRINCL
- SOCKET_SO_TYPE *
- SOCKET_TCP_CORK
So by setting the proxy, I guess I'm asking for the SOL_SOCKET:SO_TYPE group, but what about the mocked value, which is a hex binary related string as "00000000" (for keepalive) and "01000000" (reuseaddr): https://github.com/GoogleCloudPlatform/python-compat-runtime/blob/master/appengine-compat/exported_appengine_sdk/google/appengine/api/remote_socket/_remote_socket_stub.py#L97
Where can I find values like these for the (1, 3) missing pairs?
Later edit:
I've added the "SOL_SOCKET:SO_TYPE=80000000" group and now it breaks on the ssl module (which is required to be enabled in order to support https; no patching needed, just enable it in app.yaml): https://pastebin.com/9KQjdEgL by recognizing the socket type of being 128, this may be one of the following constants I guess:
- socket.MSG_EOR
- socket.SOMAXCONN
- socket.TIPC_SRC_DROPPABLE
Later...
So I realized the 128 value is actual my little-endian mocked value above, therefore I've changed the group into: "SOL_SOCKET:SO_TYPE=01000000" and this recognizes the socket.SOCK_STREAM
socket type, which actually works just for this check, but then again, it crashes, because ssl
doesn't understand GAE's custom socket object: https://pastebin.com/t2pUuW2V (<google.appengine.api.remote_socket._remote_socket.socket object at 0x7f0cd037f690>
). Tried this with and without the requests
monkey-patching.
My conclusion
The GAE custom socket
is not working entirely with SSL (on tunneling) and Python standard socket
is not working with GAE's (non-patch-able I guess) select
module, regarding the dev_appserver sandbox.
Solution: bring the same behavior of the remote deploy into the local development environment.
来源:https://stackoverflow.com/questions/49409783/google-app-engine-permission-denied-for-proxy-tunneling-on-development-server