Lua - HTTPS/tlsv1 предупреждает внутреннюю ошибку

Я пытаюсь взаимодействовать с Cleverbot API с помощью Lua. У меня есть ключ и имя пользователя, поэтому я протестировал Postman, и все сработало отлично. Затем я попытался сделать то же самое с Lua, но у меня возникла странная ошибка.

Это код:

local https = require("ssl.https")
local string = require("string")
local ltn12 = require ("ltn12")
local funcs = (loadfile "./libs/functions.lua")()

local function cleverbot(msg)
    local params = {
        ['user'] = 'SyR2nvN1cAxxxxxx',
        ['key'] = 'ckym8oDRNvpYO95GmTD14O9PuGxxxxxx',
        ['nick'] = 'cleverbot',
        ['text'] = tostring(msg),
    }

    local body = funcs.encode_table(params)
    local response = {}
    ok, code, headers, status = https.request({
        method = "POST",
        url = "https://cleverbot.io/1.0/ask/",
        headers = {
            ['Accept'] = '*/*',
            ['content-type'] = 'application/x-www-form-urlencoded',
            ['accept-encoding'] = 'gzip',
            ['content-length'] = tostring(#body),
        },
        print(tostring(ok)),
        print(tostring(code)),
        print(tostring(headers)),
        print(tostring(status)),

        source = ltn12.source.string(body),
        sink = ltn12.sink.table(response)
    })

    response = table.concat(response)

    if code ~= 200 then
       return 
    end

    if response[1] ~= nil then
       return tostring(response)
    end
end

Однако, когда я вызываю это, вот что показывают эти 4 отпечатка:

nil
tlsv1 alert internal error
nil
nil

Вместо этого я попытался подключиться с помощью HTTP, но вот что происходит:

1
301
table: 0xe5f7d60
HTTP/1.1 301 Moved Permanently

response всегда пусто. Пожалуйста, что я делаю не так? Спасибо!


person bokirov    schedule 06.12.2015    source источник
comment
То, как вы называете https.request, определенно неверно. Почему вы передаете результат функции печати в таблицу аргументов https.request?   -  person marsgpl    schedule 06.12.2015
comment
О, привет @marsgpl, я не знал, что это может повлиять на результат. Я удалил его и поставил print(ok, code, headers, status) снаружи. Я также удалил эту вещь funcs.encode_table(params) и тестирую уже отформатированную строку параметров. Я также добавил туда protocol = "tlsv1", но результат точно такой же. Что еще не так?   -  person bokirov    schedule 06.12.2015
comment
ну попробуйте проверить наличие библиотеки openssl, убедитесь, что она не устарела.   -  person marsgpl    schedule 06.12.2015
comment
Он присутствует, и я только что обновил его, @marsgpl. У меня есть другие скрипты, использующие https.request в простой форме, и они отлично работают. Единственная проблема заключается в этой общей форме, которая сообщает об ошибке tlsv1.   -  person bokirov    schedule 06.12.2015
comment
Вместо этого вы можете использовать мою библиотеку lua-http: https://github.com/daurnimator/lua-http   -  person daurnimator    schedule 07.12.2015


Ответы (1)


Мое сильное подозрение заключается в том, что целевой хост (cleverbot.io) настаивает на получении имени хоста через SNI (указание имени сервера), которое используемая вами ssl-библиотека не отправляет. Обычно в этом случае серверы используют сайт по умолчанию, но, конечно, они могут допустить сбой рукопожатия. Похоже, это именно то, что делает cloudflare (где размещается или проксируется умный бот.io).

К сожалению, нет простого способа исправить это, если только базовые ssl-библиотеки не будут изменены для использования sni с именем хоста smartbot.io для рукопожатия ssl.

Смотрите также

Fails:
openssl s_client -connect cleverbot.io:443  -tls1_1 

Succeeds:
openssl s_client -servername cleverbot.io -connect cleverbot.io:443  -tls1_1

Это означает, что не только базовые библиотеки ssl должны поддерживать sni, но также должны быть указаны, какое имя сервера использовать для промежуточного слоя привязки lua. Luasec, например, в настоящее время не использует sni, afaik

person Ctx    schedule 06.12.2015
comment
Я нашел это: github.com/brunoos/luasec/ blob/master/samples/sni/client.lua Я попробую и посмотрю, работает ли это. В противном случае я найду способ сделать это в js. Спасибо за подробный ответ! - person bokirov; 07.12.2015