【问题标题】:Google App Engine - permission denied for proxy/tunneling on development serverGoogle App Engine - 开发服务器上的代理/隧道权限被拒绝
【发布时间】:2018-08-30 18:38:21
【问题描述】:

免责声明:这不是重复的!

我正在使用 requests 库,在 GAE 标准环境下修补了猴子,一切都完美无缺,除了我在请求调用中添加额外的 proxy 参数的时候。这个代理的东西意味着隧道和套接字操作,默认情况下,开发和部署环境的标准配置都禁用了这些操作:

NotImplementedError: HTTP CONNECT Tunnelling is not supportedhttps://pastebin.com/YDsG9we7

很好,所以我们需要在我们的 GAE 平台下启用真正的套接字支持,因此添加:

env_variables: GAE_USE_SOCKETS_HTTPLIB : "True"

即使没有做请求工具带猴子补丁(根本不使用 urlfetch),我们也会获得一个权限被拒绝:https://pastebin.com/ifBFKi3K

这通常发生在沙盒认为您正在访问禁止的服务器位置或端口时,但代理功能齐全,猜猜是什么,我测试了完全相同的代码(没有任何由于开发或将服务器部署为当前环境而添加/删除的功能)并且它在部署时按预期工作,没有任何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 导入等替换为标准的 Python 接口
    • 问题ValueError: select only supported on socket objects.https://pastebin.com/gHFM6QiF;这在某种程度上预计会发生,因为由于标准sockets导入但GAE自己的select,预期的套接字对象与预期的不同(并且通过从解释器的内存中删除选择只会导致更多问题或不起作用完全),所以我也想用标准的pythonic模块替换select模块(内置),我该怎么做?

没关系...

是否有任何方法可以结束这场噩梦并仍然使用标准环境?如果它在没有任何补丁的情况下在部署服务器上工作,为什么不应该也与 dev_appserver 工具一起工作?

我只是不想再做任何补丁,我只想克服在远程部署服务器下不会抛出的Permission denied 错误,使用相同的代码逻辑,无论我们是否使用请求, urlfetch、httplib、sockets 等(只是代理所需的隧道)。

【问题讨论】:

  • 进一步挖掘问题:

标签: python sockets google-app-engine proxy tunneling


【解决方案1】:

进一步挖掘问题,似乎在这个文件中:

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" (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

在哪里可以找到 (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 猴子补丁。

我的结论

GAE 自定义 socket 不能完全使用 SSL(关于隧道),Python 标准 socket 不能使用 GAE 的(我猜是不可修补的)select 模块,关于 dev_appserver 沙箱。

解决方案:将远程部署的相同行为引入本地开发环境。

【讨论】:

  • 您可以在 Google 的公共问题卡车司机中打开 Feature Request
猜你喜欢
  • 2018-11-24
  • 1970-01-01
  • 1970-01-01
  • 2014-10-03
  • 2018-01-15
  • 1970-01-01
  • 1970-01-01
  • 2015-12-01
  • 2021-03-04
相关资源
最近更新 更多