telegram-bot-rb / telegram-bot

Ruby gem for building Telegram Bot with optional Rails integration
MIT License
635 stars 118 forks source link

Connection to telegram server mishandling certificate leading to mistaken 'expired' conclusion #178

Closed dvodvo closed 2 years ago

dvodvo commented 2 years ago

bundle exec rake telegram:bot:set_webhook RAILS_ENV=development will fail with gem version 0.15.4, rails 6.1.3.2, ruby 2.6.1

In examining the stack trace, there are two obvious break points to examine and get object information, the first in each of these blocks:

/home/deploy/the_app/shared/bundle/ruby/2.6.0/gems/httpclient-2.8.3/lib/httpclient/ssl_socket.rb:103:in `ssl_connect'
/home/deploy/the_app/shared/bundle/ruby/2.6.0/gems/httpclient-2.8.3/lib/httpclient/ssl_socket.rb:41:in `initialize'
/home/deploy/the_app/shared/bundle/ruby/2.6.0/gems/httpclient-2.8.3/lib/httpclient/ssl_socket.rb:26:in `new'
/home/deploy/the_app/shared/bundle/ruby/2.6.0/gems/httpclient-2.8.3/lib/httpclient/ssl_socket.rb:26:in `create_socket'
/home/deploy/the_app/shared/bundle/ruby/2.6.0/gems/httpclient-2.8.3/lib/httpclient/session.rb:752:in `block in connect'
/home/deploy/the_app/shared/bundle/ruby/2.6.0/gems/httpclient-2.8.3/lib/httpclient/session.rb:748:in `connect'
/home/deploy/the_app/shared/bundle/ruby/2.6.0/gems/httpclient-2.8.3/lib/httpclient/session.rb:511:in `query'
/home/deploy/the_app/shared/bundle/ruby/2.6.0/gems/httpclient-2.8.3/lib/httpclient/session.rb:177:in `query'
/home/deploy/the_app/shared/bundle/ruby/2.6.0/gems/httpclient-2.8.3/lib/httpclient.rb:1242:in `do_get_block'
/home/deploy/the_app/shared/bundle/ruby/2.6.0/gems/httpclient-2.8.3/lib/httpclient.rb:1019:in `block in do_request'
/home/deploy/the_app/shared/bundle/ruby/2.6.0/gems/httpclient-2.8.3/lib/httpclient.rb:1133:in `protect_keep_alive_disconnected'
/home/deploy/the_app/shared/bundle/ruby/2.6.0/gems/httpclient-2.8.3/lib/httpclient.rb:1014:in `do_request'
/home/deploy/the_app/shared/bundle/ruby/2.6.0/gems/httpclient-2.8.3/lib/httpclient.rb:856:in `request'
/home/deploy/the_app/shared/bundle/ruby/2.6.0/gems/httpclient-2.8.3/lib/httpclient.rb:765:in `post'
/home/deploy/the_app/shared/bundle/ruby/2.6.0/gems/telegram-bot-0.15.4/lib/telegram/bot/client.rb:82:in `http_request'

/home/deploy/the_app/shared/bundle/ruby/2.6.0/gems/telegram-bot-0.15.4/lib/telegram/bot/client.rb:73:in `request'
/home/deploy/the_app/shared/bundle/ruby/2.6.0/gems/telegram-bot-0.15.4/lib/telegram/bot/async.rb:151:in `request'
/home/deploy/the_app/shared/bundle/ruby/2.6.0/gems/telegram-bot-0.15.4/lib/telegram/bot/client/api_helper.rb:22:in `block (2 levels) in define_helpers'
/home/deploy/the_app/shared/bundle/ruby/2.6.0/gems/telegram-bot-0.15.4/lib/telegram/bot/tasks.rb:16:in `block in set_webhook'
/home/deploy/the_app/shared/bundle/ruby/2.6.0/gems/telegram-bot-0.15.4/lib/telegram/bot/tasks.rb:55:in `block (2 levels) in each_bot'
/home/deploy/the_app/shared/bundle/ruby/2.6.0/gems/telegram-bot-0.15.4/lib/telegram/bot/async.rb:138:in `async'
/home/deploy/the_app/shared/bundle/ruby/2.6.0/gems/telegram-bot-0.15.4/lib/telegram/bot/tasks.rb:55:in `block in each_bot'
/home/deploy/the_app/shared/bundle/ruby/2.6.0/gems/telegram-bot-0.15.4/lib/telegram/bot/tasks.rb:55:in `each'
/home/deploy/the_app/shared/bundle/ruby/2.6.0/gems/telegram-bot-0.15.4/lib/telegram/bot/tasks.rb:55:in `each_bot'
/home/deploy/the_app/shared/bundle/ruby/2.6.0/gems/telegram-bot-0.15.4/lib/telegram/bot/tasks.rb:12:in `set_webhook'
/home/deploy/the_app/shared/bundle/ruby/2.6.0/gems/telegram-bot-0.15.4/lib/tasks/telegram-bot.rake:17:in `block (3 levels) in <main>'
/home/deploy/the_app/shared/bundle/ruby/2.6.0/gems/rake-13.0.3/exe/rake:27:in `<top (required)>'
/home/deploy/.rbenv/versions/2.6.1/bin/bundle:23:in `load'
/home/deploy/.rbenv/versions/2.6.1/bin/bundle:23:in `<main>'
Tasks: TOP => telegram:bot:set_webhook

In intercepting lib/telegram/bot/client.rb:73 the following were being generated for uri and body and leading to error OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=error: certificate verify failed (certificate has expired):

uri:  https://#{my_domain}//bot#{bot_id}:#{bot_token}/setWebhook
body {:url=>"https://#{my_domain}/telegram/#{unique_string_which_does_route_to_controller}", :certificate=>nil, :ip_address=>nil, :drop_pending_updates=>false}

The uri has the curiosity of having a double slash.

The body is quite telling (I believe one issue is that it states the certificate as nil) as if the gem is looking for a client authentication certificate. Now here is the kicker: using the API directly

curl -F "url=https://#{my_domain}/telegram/#{unique_string_which_does_route_to_controller}" https://api.telegram.org/bot#{bot_id}:#{bot_token}/setWebhook/setWebhook

sets the webhook appropriately! The Telegram server does the cert check and its validation passes.

All other actions, such as respond_with :message hit the same (certificate has expired) error presumably for the same motive.

Having another application on another server, older gem version 0.14.4, this does not occur.

side note This may be pertinent.. I never managed to start the server with the indications of syntax for the controller: class Telegram::WebhookController < Telegram::Bot::UpdatesController but had to use, as per the example app class TelegramWebhooksController < Telegram::Bot::UpdatesController with routes set as telegram_webhook TelegramWebhooksController

kewogc commented 2 years ago

+1 some by get webhook 2022-03-10 20-12-27.047] [ActiveJob] [Telegram::Bot::Client::AsyncJob] [00235614-1ea9-40fa-ab4b-53106aec141a] Error performing Telegram::Bot::Client::AsyncJob (Job ID: 00235614-1ea9-40 fa-ab4b-53106aec141a) from Async(default) in 238.43ms: OpenSSL::SSL::SSLError (SSL_connect returned=1 errno=0 state=error: certificate verify failed (certificate has expired)): /home/deploy/tgbot/shared/bundle/ruby/2.6.0/gems/httpclient-2.8.3/lib/httpclient/ssl_socket.rb:103:inconnect'
/home/deploy/tgbot/shared/bundle/ruby/2.6.0/gems/httpclient-2.8.3/lib/httpclient/ssl_socket.rb:103:in ssl_connect' /home/deploy/tgbot/shared/bundle/ruby/2.6.0/gems/httpclient-2.8.3/lib/httpclient/ssl_socket.rb:41:ininitialize'
/home/deploy/tgbot/shared/bundle/ruby/2.6.0/gems/httpclient-2.8.3/lib/httpclient/ssl_socket.rb:26:in new' /home/deploy/tgbot/shared/bundle/ruby/2.6.0/gems/httpclient-2.8.3/lib/httpclient/ssl_socket.rb:26:increate_socket'
/home/deploy/tgbot/shared/bundle/ruby/2.6.0/gems/httpclient-2.8.3/lib/httpclient/session.rb:752:in block in connect' /home/deploy/.rvm/rubies/ruby-2.6.3/lib/ruby/2.6.0/timeout.rb:93:inblock in timeout' `

printercu commented 2 years ago

Do you use self-signed cert? Do you provide it with CERT option?

See more details in https://github.com/telegram-bot-rb/telegram-bot/wiki/Deployment#webhooks

dvodvo commented 2 years ago

Hello,

No, I am not using a self-signed cert, but one issued via lets encrypt.

On Sat, Mar 12, 2022, at 19:30, Max Melentiev wrote:

Do you use self-signed cert? Do you provide it with CERT option?

See more details in https://github.com/telegram-bot-rb/telegram-bot/wiki/Deployment#webhooks

— Reply to this email directly, view it on GitHub https://github.com/telegram-bot-rb/telegram-bot/issues/178#issuecomment-1065937538, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAFO2YTFCRGRWNE23PDDCGLU7TPF3ANCNFSM5PG4S5MQ. Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub. You are receiving this because you authored the thread.Message ID: @.***>

printercu commented 2 years ago

Could you please share a host name of the server you use for a webhook url?

joshkurien commented 2 years ago

I had faced exactly the same issues, but on digging deeper, for me the issue was on https://github.com/telegram-bot-rb/telegram-bot/blob/master/lib/telegram/bot/client.rb#L58

    def initialize(token = nil, username = nil, server: SERVER, **options)
        @client = HTTPClient.new
        @token = token || options[:token]
        @username = username || options[:username]
        @base_uri = format(URL_TEMPLATE, server: server, token: self.token)
      end

Here instead of getting the constant SERVER defined on the file, the argument is being overwritten by my bot server URL from the config. not sure why this is happening, but the way i fixed this was by simply changing base_uri format to

   @base_uri = format(URL_TEMPLATE, server: SERVER, token: self.token)

in order to pick from the constant instead of a variable argument. This should be fine as the telegram host would never change either.

joshkurien commented 2 years ago

Apologies, the above comment was because of a misunderstanding... Simply removing the server config from my bot configs resolved my issue