New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using bot as https destination without ngrok #76
Comments
The bot will spawn a tiny server to listen for updates using the default SSL context (no encryption). You have to define a custom SSL context (read below). Here are the steps I followed: The generated .pem will also include the private key, you have to strip it and send only the public key to Telegram (setWebhook). Create and set as default a custom SSL context: relevant Akka-HTTP instructions using the certificates you generated. Beware of the allowed ports. Let me know if you have any issue. |
Here's the modified import java.io.{File, FileInputStream, InputStream}
import java.net.URLEncoder
import java.nio.file.Paths
import java.security.{KeyStore, SecureRandom}
import akka.http.scaladsl.{ConnectionContext, Http, HttpsConnectionContext}
import akka.http.scaladsl.model.{HttpRequest, Uri}
import akka.http.scaladsl.unmarshalling.Unmarshal
import com.bot4s.telegram.api.Webhook
import com.bot4s.telegram.methods._
import com.bot4s.telegram.models.{InputFile, Message}
import javax.net.ssl.{KeyManagerFactory, SSLContext, TrustManagerFactory}
import scala.concurrent.duration.Duration
import scala.concurrent.{Await, Future}
/**
* Webhook-backed JS calculator.
* To test Webhooks locally, use an SSH tunnel or ngrok.
*/
class WebhookBot(token: String) extends AkkaExampleBot(token) with Webhook {
val port = 443
val webhookUrl = "https://12.34.56.78"
override val interfaceIp: String = "0.0.0.0"
val baseUrl = "http://api.mathjs.org/v1/?expr="
override def certificate: Option[InputFile] = Some(
InputFile(new File("/root/bot/telegram/stripped.pem").toPath)
)
override def receiveMessage(msg: Message): Future[Unit] = {
msg.text.fold(Future.successful(())) { text =>
val url = baseUrl + URLEncoder.encode(text, "UTF-8")
for {
res <- Http().singleRequest(HttpRequest(uri = Uri(url)))
if res.status.isSuccess()
result <- Unmarshal(res).to[String]
_ <- request(SendMessage(msg.source, result))
} yield ()
}
}
// Set custom context.
Http().setDefaultServerHttpContext(httpsContext())
def httpsContext(): HttpsConnectionContext = {
// Manual HTTPS configuration
val password: Array[Char] = "password".toCharArray // do not store passwords in code, read them from somewhere safe!
val ks: KeyStore = KeyStore.getInstance("PKCS12")
val keystore: InputStream = new FileInputStream("/root/bot/telegram/keystore.p12") // getClass.getClassLoader.getResourceAsStream("server.p12")
require(keystore != null, "Keystore required!")
ks.load(keystore, password)
val keyManagerFactory: KeyManagerFactory = KeyManagerFactory.getInstance("SunX509")
keyManagerFactory.init(ks, password)
val tmf: TrustManagerFactory = TrustManagerFactory.getInstance("SunX509")
tmf.init(ks)
val sslContext: SSLContext = SSLContext.getInstance("TLS")
sslContext.init(keyManagerFactory.getKeyManagers, tmf.getTrustManagers, new SecureRandom)
val https: HttpsConnectionContext = ConnectionContext.https(sslContext)
https
}
}
object Main {
def main(args: Array[String]): Unit = {
val bot = new WebhookBot(System.getenv("BOT_TOKEN"))
val token = bot.run()
println("Press [ENTER] to shutdown")
readLine()
bot.shutdown()
Await.result(token, Duration.Inf)
}
} |
Hello @mukel. --#1
keytool -genkey -keyalg RSA -alias mtspredbot -keystore mtspredbot.jks -storepass yyyyy -validity 360 -keysize 2048
First and Last name = 12.34.56.78
on each question, I type my IP : 12.34.56.78
Enter key password for <mtspredbot>
(RETURN if same as keystore password):
Re-enter new password:
--#2
keytool -importkeystore -srckeystore mtspredbot.jks -destkeystore mtspredbot.p12 -srcstoretype jks -deststoretype pkcs12
Entry for alias mtspredbot successfully imported.
Import command completed: 1 entries successfully imported, 0 entries failed or cancelled
--#3
C:\tcert>C:\openssl\openssl pkcs12 -in mtspredbot.p12 -out mtspredbot.pem
Enter Import Password:
MAC verified OK
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
--#4
C:\openssl\openssl rsa -in mtspredbot.pem -pubout > mtspredbot.pub
After this steps I try run bot and receive next message: [trace, com.bot4s.telegram.clients.AkkaHttpClient] REQUEST fe6e6ef6-8008-4c57-80e1-6ce6b15e9e76 SetWebhook(https://12.34.56.78,Some(Path(C:\tcert\mtspredbot.pub)),None,None)
Press [ENTER] to shutdown the bot, it may take a few seconds...
[error, com.bot4s.telegram.clients.AkkaHttpClient] RESPONSE fe6e6ef6-8008-4c57-80e1-6ce6b15e9e76 com.bot4s.telegram.api.TelegramApiException: Bad Request: bad webhook: Failed to set custom certificate file I have some doubts about step #4 openssl rsa ... Next time I try with pem [trace, com.bot4s.telegram.clients.AkkaHttpClient] REQUEST 5f8a5488-ebff-471e-aea3-63bb18a5f798 SetWebhook(https://12.34.56.78,Some(Path(C:\tcert\mtspredbot.pem)),None,None)
Press [ENTER] to shutdown the bot, it may take a few seconds...
[trace, com.bot4s.telegram.clients.AkkaHttpClient] RESPONSE 5f8a5488-ebff-471e-aea3-63bb18a5f798 true No errors, but bot don't receive something. |
I had the same issue (no error, but didn't work), I stripped the .pem file manually, just leave the public key e.g. |
I stripped .pem manually, but when I stay part 09:41:02.590 [main] INFO mtspredbot.Main$ - webhookUrl=https://12.34.56.78 port=8443
[trace, com.bot4s.telegram.clients.AkkaHttpClient] REQUEST 319a444e-9e4a-43a2-85a4-03af837971de SetWebhook(https://12.34.56.78,Some(Path(C:\tcert\mtspredbot.pem)),None,None)
Press [ENTER] to shutdown the bot, it may take a few seconds...
[error, com.bot4s.telegram.clients.AkkaHttpClient] RESPONSE 319a444e-9e4a-43a2-85a4-03af837971de com.bot4s.telegram.api.TelegramApiException: Bad Request: bad webhook: Failed to set custom certificate file Then I try form: 09:44:21.683 [main] INFO mtspredbot.Main$ - webhookUrl=https://12.34.56.78 port=8443
[trace, com.bot4s.telegram.clients.AkkaHttpClient] REQUEST 21ceee1f-5578-477a-a0dd-341b93a858a2 SetWebhook(https://12.34.56.78,Some(Path(C:\tcert\mtspredbot.pem)),None,None)
Press [ENTER] to shutdown the bot, it may take a few seconds...
[trace, com.bot4s.telegram.clients.AkkaHttpClient] RESPONSE 21ceee1f-5578-477a-a0dd-341b93a858a2 true I can connect to bot with telnet from remote machine:
May be we need create public key instead of public certificate Will continue my investigation. |
Did you specified the 8443 port in the webhook url? Otherwise it's 443 by default. |
"Did you specified the 8443 port in the webhook url?", NO ...
class telegBotWH(log :org.slf4j.Logger,
config :Config,
sessSrc :CassSessionSrc)
extends AkkaTelegramBot
with Webhook
with CommonFuncs
with Commands[Future]
{
LoggerConfig.factory = PrintLoggerFactory()
LoggerConfig.level = LogLevel.TRACE
...
val port :Int = 8443
val webhookUrl =
... I will try port in url, like this https://12.34.56.78:8443 |
messages from telegram servers. Bot communicate with telegram servers via local installed 3proxy through SOCKS. Thanks author of bot4 "Alfonso² Peterssen" and issue bot4s/telegram#76
Oh, Thanks so much, we solve it. url = https://12.34.56.78:8443 Bag Attributes
friendlyName: mtspredbot
localKeyID: 54 69.... ..
-----BEGIN CERTIFICATE----- hexstaffhere
-----END CERTIFICATE----- Also want add that for output connection from bot to telegram it's useful 3proxy (SOCKS), because telegram locked in Russia. nserver dns1ip
nserver dns2ip
nscache 65536
timeouts 1 5 30 60 180 1800 15 60
service
log c:\3proxy\logs\3proxy.log D
logformat "- +_L%t.%. %N.%p %E %U %C:%c %R:%r %O %I %h %T"
archiver rar rar a -df -inul %A %F
rotate 30
auth iponly
allow * 127.0.0.1, 12.34.56.78 * *
external 0.0.0.0
internal 12.34.56.78
maxconn 20
socks where 12.34.56.78 static ip of VDS and in the project application.conf additionally akka {
http.client.proxy {
https {
host = "12.34.56.78"
port = 1080
}}} of course open port 1080 in FW. I am going use this Bot for full control of Information system inside VDS. Thanks one more time. |
Do I need (may) to close this issue? |
Great, about the high CPU load: When using polling, the bot retry immediately if |
Hello @mukel
I try to use your library like this:
class telegBotWH(log :org.slf4j.Logger, config :Config) extends AkkaTelegramBot with Webhook with Commands[Future] { ...
and next want explisitely load certificate with:
val cfile :java.io.File= new File("C:\\tcert\\mtspredbot.pem") val inpCertFilePath :java.nio.file.Path = cfile.toPath override val certificate :Option[InputFile] = Option(InputFile(inpCertFilePath))
I use next WebHook address https://xxx.xxx.xxx.xxx
where xxx.xxx.xxx.xxx is my VDS
When I run bot there is next output
[trace, com.bot4s.telegram.clients.AkkaHttpClient] REQUEST 5ebe2b43-f7da-4fe9-80f3-a04448d3df8e SetWebhook(https://xxx.xxx.xxx.xxx,Some(Path(C:\tcert\mtspredbot.pem)),None,None) Press [ENTER] to shutdown the bot, it may take a few seconds... [trace, com.bot4s.telegram.clients.AkkaHttpClient] RESPONSE 5ebe2b43-f7da-4fe9-80f3-a04448d3df8e true [WARN] [06/28/2019 15:58:30.996] [default-akka.actor.default-dispatcher-16] [akka.actor.ActorSystemImpl(default)] Illegal request, responding with status '400 Bad Request': Unsupported HTTP method: The HTTP method started with 0x16 rather than any known HTTP method. Perhaps this was an HTTPS request sent to an HTTP endpoint?
My question. Is it possible to use bot wuth this configuration as destination for telegram with https.
I know about ngrok and it works fine but wants to use it directly, because it's vds.
The text was updated successfully, but these errors were encountered: