Google App Engine - 开发服务器上 proxy/tunneling 的权限被拒绝
Google App Engine - permission denied for proxy/tunneling on development server
免责声明:这不是重复的!
我正在使用请求库,在 GAE 标准环境下修补猴子,一切都完美无缺,除了我在请求调用中添加额外的 proxy
参数的时候。这个代理意味着隧道和套接字操作,默认情况下开发和部署环境的标准配置禁用:
NotImplementedError: HTTP CONNECT Tunnelling is not supported
https://pastebin.com/YDsG9we7
很好,所以我们需要在我们的 GAE 平台下启用真正的套接字支持,因此添加:
env_variables:
GAE_USE_SOCKETS_HTTPLIB : "True"
即使不执行请求工具带猴子补丁(根本不使用 urlfetch),我们也会被拒绝许可:https://pastebin.com/ifBFKi3K
这通常发生在沙箱认为您正在访问禁止的服务器位置或端口时,但代理功能齐全并且猜猜是什么,我已经测试了完全相同的代码(由于开发或将服务器部署为当前环境,没有任何 added/removed 功能)并且它在部署时按预期工作,没有任何类型的 Permission denied
错误,通过使请求完全成功(如果我们尝试不启用 httplib 套接字,在两种情况下我们仍然会遇到 Tunnelling is not supported
错误,这是预期的行为)。
现在,我在部署上有了一个可行的解决方案(这才是真正重要的),但这对我来说还不够,我只想在我的开发服务器和环境下通过代理测试这些请求,所以我尝试做的是以下内容:
- 让我们通过应用这些来导入我们自己的标准套接字库:"ImportError: No module named _ssl" with dev_appserver.py from Google App Engine
- 不能猴子修补 sandbox.py 文件以列入白名单
_sockets
和 _ssl
等,没问题,我已经将它直接在磁盘上硬修补到原始文件
- 将默认套接字、httplib 导入等替换为标准的 pythonic 套接字
- 问题:
ValueError: select only supported on socket objects.
https://pastebin.com/gHFM6QiF ;这在某种程度上是预期会发生的,因为预期的套接字对象与预期的不同,这是由于标准 sockets
导入但 GAE 自己的 select
(并通过从解释器的内存中删除 select只会导致更多问题或根本无法工作),所以我想用标准的 pythonic 模块替换 select
模块(这是一个内置模块),我该怎么做?
没关系...
有什么方法可以结束这场噩梦并继续使用标准环境吗?如果它在没有任何补丁的情况下在部署服务器上运行,为什么不也可以使用 dev_appserver 工具呢?
我只是不想做更多的补丁,我只是想克服远程部署服务器下不会抛出的 Permission denied
错误,使用完全相同的代码逻辑,无论是否我们使用请求、urlfetch、httplib、套接字等(只是代理所需的隧道)。
Digged-in 问题更进一步,似乎在这个文件中:
platform/google_appengine/google/appengine/api/remote_socket/_remote_socket_stub.py 在常量 _MOCK_SOCKET_OPTIONS
中找到一些模拟套接字对 (level, option) 缺少 (1, 3 ) 对,我的意思是下面的级别和选项的乘积之一(我猜星号是所需的值):
级别(值:1):
- SOCKET_TCP_NODELAY
- SOCKET_IP_TOS
- SOCKET_SOL_SOCKET *
- SOCKET_SO_DEBUG
选项(值:3):
- SOCKET_IP_HDRINCL
- SOCKET_SO_TYPE *
- SOCKET_TCP_CORK
所以通过设置代理,我想我是在请求 SOL_SOCKET:SO_TYPE 组,但是模拟值呢?是一个十六进制二进制相关字符串,如“00000000”(用于保持活动)和“01000000”(重用地址):https://github.com/GoogleCloudPlatform/python-compat-runtime/blob/master/appengine-compat/exported_appengine_sdk/google/appengine/api/remote_socket/_remote_socket_stub.py#L97
在哪里可以找到 (1, 3) 个缺失对的此类值?
稍后编辑:
我已经添加了 "SOL_SOCKET:SO_TYPE=80000000" 组,现在它在 ssl 模块上中断(需要启用以支持 https;无需修补,只需在 app.yaml 中启用它): https://pastebin.com/9KQjdEgL
通过识别 128 的套接字类型,我猜这可能是以下常量之一:
- socket.MSG_EOR
- socket.SOMAXCONN
- socket.TIPC_SRC_DROPPABLE
稍后...
所以我意识到 128 值实际上是我上面的 little-endian 模拟值,因此我将组更改为:"SOL_SOCKET:SO_TYPE=01000000" 并且它识别 socket.SOCK_STREAM
套接字类型,它实际上仅适用于此检查,但它再次崩溃,因为 ssl
不理解 GAE 的自定义套接字对象:https://pastebin.com/t2pUuW2V (<google.appengine.api.remote_socket._remote_socket.socket object at 0x7f0cd037f690>
)。在有和没有 requests
monkey-patching.
的情况下都试过了
我的结论
GAE 自定义 socket
不能完全与 SSL 一起工作(在隧道上)并且 Python 标准 socket
不能与 GAE 一起工作(non-patch-able 我猜)select
模块,关于 dev_appserver 沙箱。
解决方案:将远程部署的相同行为引入本地开发环境。
免责声明:这不是重复的!
我正在使用请求库,在 GAE 标准环境下修补猴子,一切都完美无缺,除了我在请求调用中添加额外的 proxy
参数的时候。这个代理意味着隧道和套接字操作,默认情况下开发和部署环境的标准配置禁用:
NotImplementedError: HTTP CONNECT Tunnelling is not supported
https://pastebin.com/YDsG9we7
很好,所以我们需要在我们的 GAE 平台下启用真正的套接字支持,因此添加:
env_variables:
GAE_USE_SOCKETS_HTTPLIB : "True"
即使不执行请求工具带猴子补丁(根本不使用 urlfetch),我们也会被拒绝许可:https://pastebin.com/ifBFKi3K
这通常发生在沙箱认为您正在访问禁止的服务器位置或端口时,但代理功能齐全并且猜猜是什么,我已经测试了完全相同的代码(由于开发或将服务器部署为当前环境,没有任何 added/removed 功能)并且它在部署时按预期工作,没有任何类型的 Permission denied
错误,通过使请求完全成功(如果我们尝试不启用 httplib 套接字,在两种情况下我们仍然会遇到 Tunnelling is not supported
错误,这是预期的行为)。
现在,我在部署上有了一个可行的解决方案(这才是真正重要的),但这对我来说还不够,我只想在我的开发服务器和环境下通过代理测试这些请求,所以我尝试做的是以下内容:
- 让我们通过应用这些来导入我们自己的标准套接字库:"ImportError: No module named _ssl" with dev_appserver.py from Google App Engine
- 不能猴子修补 sandbox.py 文件以列入白名单
_sockets
和_ssl
等,没问题,我已经将它直接在磁盘上硬修补到原始文件 - 将默认套接字、httplib 导入等替换为标准的 pythonic 套接字
- 问题:
ValueError: select only supported on socket objects.
https://pastebin.com/gHFM6QiF ;这在某种程度上是预期会发生的,因为预期的套接字对象与预期的不同,这是由于标准sockets
导入但 GAE 自己的select
(并通过从解释器的内存中删除 select只会导致更多问题或根本无法工作),所以我想用标准的 pythonic 模块替换select
模块(这是一个内置模块),我该怎么做?
- 不能猴子修补 sandbox.py 文件以列入白名单
没关系...
有什么方法可以结束这场噩梦并继续使用标准环境吗?如果它在没有任何补丁的情况下在部署服务器上运行,为什么不也可以使用 dev_appserver 工具呢?
我只是不想做更多的补丁,我只是想克服远程部署服务器下不会抛出的 Permission denied
错误,使用完全相同的代码逻辑,无论是否我们使用请求、urlfetch、httplib、套接字等(只是代理所需的隧道)。
Digged-in 问题更进一步,似乎在这个文件中:
platform/google_appengine/google/appengine/api/remote_socket/_remote_socket_stub.py 在常量 _MOCK_SOCKET_OPTIONS
中找到一些模拟套接字对 (level, option) 缺少 (1, 3 ) 对,我的意思是下面的级别和选项的乘积之一(我猜星号是所需的值):
级别(值:1):
- SOCKET_TCP_NODELAY
- SOCKET_IP_TOS
- SOCKET_SOL_SOCKET *
- SOCKET_SO_DEBUG
选项(值:3):
- SOCKET_IP_HDRINCL
- SOCKET_SO_TYPE *
- SOCKET_TCP_CORK
所以通过设置代理,我想我是在请求 SOL_SOCKET:SO_TYPE 组,但是模拟值呢?是一个十六进制二进制相关字符串,如“00000000”(用于保持活动)和“01000000”(重用地址):https://github.com/GoogleCloudPlatform/python-compat-runtime/blob/master/appengine-compat/exported_appengine_sdk/google/appengine/api/remote_socket/_remote_socket_stub.py#L97
在哪里可以找到 (1, 3) 个缺失对的此类值?
稍后编辑:
我已经添加了 "SOL_SOCKET:SO_TYPE=80000000" 组,现在它在 ssl 模块上中断(需要启用以支持 https;无需修补,只需在 app.yaml 中启用它): https://pastebin.com/9KQjdEgL 通过识别 128 的套接字类型,我猜这可能是以下常量之一:
- socket.MSG_EOR
- socket.SOMAXCONN
- socket.TIPC_SRC_DROPPABLE
稍后...
所以我意识到 128 值实际上是我上面的 little-endian 模拟值,因此我将组更改为:"SOL_SOCKET:SO_TYPE=01000000" 并且它识别 socket.SOCK_STREAM
套接字类型,它实际上仅适用于此检查,但它再次崩溃,因为 ssl
不理解 GAE 的自定义套接字对象:https://pastebin.com/t2pUuW2V (<google.appengine.api.remote_socket._remote_socket.socket object at 0x7f0cd037f690>
)。在有和没有 requests
monkey-patching.
我的结论
GAE 自定义 socket
不能完全与 SSL 一起工作(在隧道上)并且 Python 标准 socket
不能与 GAE 一起工作(non-patch-able 我猜)select
模块,关于 dev_appserver 沙箱。
解决方案:将远程部署的相同行为引入本地开发环境。