Telegram Javabot. Setting webhook - java

I've created telegram bot on Java with rubenlagus api.And now I can't setup webhook. I know these rules for webhook:
*Supports IPv4, IPv6 is currently not supported for Webhooks.
*Accepts incoming POSTs from 149.154.167.197-233 on port 443,80,88 or 8443.
*Is able to handle TLS1.0+ HTTPS-traffic.
*Provides a supported, non-wildcard, verified or self-signed certificate.
*Uses a CN or SAN that matches the domain you’ve supplied on setup.
*Supplies all intermediate certificates to complete a verification chain.
I have a domain name with verified ssl certificate.Qualys test shows A+ rank.Server Supports IPv4. 443
port is listening. And server accepts incoming POSTs from 149.154.167.197-233 on port 443. I use this rubenlagus api method for creating TelegramApi
private static TelegramBotsApi createNoSelfSignedTelegramBotsApi() throws TelegramApiException {
return new TelegramBotsApi(
"src/main/resources/server.jks",//path to KeyStore for the server
"myPassword", //Key store password for the serve
"https://example.com:443", //External url
"https://localhost:443"); //Internal url
}
I've obtained server.jks via these commands
openssl pkcs12 -export -in mydomain.net.crt -inkey mydomain.key > keypair.p12
keytool -importkeystore -srckeystore keypair.p12 -destkeystore server.jks -srcstoretype pkcs12
This is my code:
ApiContextInitializer.init();
TelegramBotsApi botsApi = new TelegramBotsApi(
"src/main/resources/server.jks",
"mypassword",
"https://example.com:443",
"https://localhost:443");
BotHook webhookBot = new BotHook(options);
botsApi.registerBot(webhookBot);
When i start program, i recieve this
Jul 28, 2018 3:27:59 PM
org.glassfish.grizzly.http.server.NetworkListener start
INFO: Started listener bound to [localhost:443]
Jul 28, 2018 3:27:59 PM org.glassfish.grizzly.http.server.HttpServer
start
INFO: [HttpServer] Started.
But bot don't work.I see this in server's logs:
2018/07/29 15:08:43 [error] 1166#1166: *453 openat() "/var/www/www->root/data/www/example.net/callback/WebhookClass failed (2: No such file or >directory),
client: 149.154.167.227, server: example.net request: "POST >/callback/WebhookClass HTTP/1.1", host: "example.net"
It seems like Grizzly can't handle http request. When i'm trying to check it via this curl command
curl -X POST -i http://217.0.0.1:443/callback
I recieve this
curl: (7) Failed to connect to 217.0.0.1 port 443: Connection timed out
I checked many times all parameters passed in TelegramBotsApi constructor.

Seems like problem with your infrastructure, not code. TelegramBotsApi starts http Grizzly server on port 443 which handles bot related requests from Telegram. Telegram will access server by it's external URL https://example.com:443.
Server's logs your provided looks like it is Nginx, am I right? So I assume your have Nginx server configured to accept requests for https://example.com:443. Requests from Telegram are handled by Nginx and not by Grizzly server. Nginx answers with 404 because it has no handlers configured on /callback/* path.
You have several options to make requests from Telegram sent to example.com to be forwarded to Grizzly:
Run your program on server where nginx is running. You need use another port, 8443 for example. Setup your server's firewall rules to allow incoming connections on 8443.
Configure nginx to forward all http request matching /callback/* to your Grizzly server. Add following to server section of nginx config file:
location /callback {
proxy_pass https://<YOUR_TELEGRAM_BOT_SERVER>:443;
}
Where YOUR_TELEGRAM_BOT_SERVER is host name or IP of server running your program. When registering bot api make sure to use the same certificate as your nginx server.

Related

AWS EC2 with Elastic Load balancer not sending SSL Certificate

I have a server that is sending an HTTPPost request with the Apache HttpClient in Java. I am trying to send the post with my cert attached for validation and the other side is saying they are not receiving anything SSL information. I inherited this code/server setup with minimal documentation so I don't necessarily know it was set up properly in the first place.
Here is the setup.
AWS EC2 server. Linux
Elastic Load balancer setup with SSL Cert.
a. Verified this is working as intended when I visit the server via port 443
Tomcat7 running API server
Java 1.8.0_251
Apache httpclient-4.5.9
Being that there are ways to attach the certificate to each level of this I don't fully understand where the problem is.
Most of the ways I have found revolve around attaching the SSL to the outgoing request in the httpclient object but have been unsuccessful. They are a variation on the following...
KeyStore identityKeyStore = KeyStore.getInstance("JKS");
identityKeyStore.load(identity_file, CERTPASSWORD.toCharArray());
SSLContext sslContext = SSLContexts.custom()
.loadKeyMaterial(identityKeyStore, CERTPASSWORD.toCharArray()).build(); // load client certificate
sslConnectionSocketFactory = new SSLConnectionSocketFactory(
sslContext,
new String[]{"TLSv1.2", "TLSv1.1"},
null,
SSLConnectionSocketFactory.getDefaultHostnameVerifier());
This has not worked and I have verified the .jks file is properly formatted and verified the password. Although if this works as I test on a windows machine I would assume this would be the best option.
This server only has outgoing requests to a few sources all of which will need to be SSL verified so I don't mind if it is sent on every outgoing https request.
Is there somewhere else in my setup that I should be looking into attaching the certificate?
If there is a Load balancer with SSL configured then the SSL stops at the load balancer, and your client certificate is never making it to the server. Client SSL certificates only get passed to the server when the server has an SSL certificate installed on it, and the load balancer is in TCP passthrough mode.

java https://localhost (SSL) - possible without installing certs on client?

After reading the following, I'm still stuck on making the barest-minimum https://localhost stand-alone install-free webserver java app. It needs to be library-free, use Java 8, and accept connections from the browser without first installing any special client certs. I'm unclear if this is at all possible with self-signed certs because it only has to work for "localhost".
How make SSL server socket support both http & https in java?
My simple java HTTPS server only works for localhost
Simple Java HTTPS server
So far I've generated some key files using
openssl genrsa -aes128 -out privkey.pem 2048 # makes privkey.pem
openssl req -new -x509 -key privkey.pem # makes cert.crt
and I've cobbled together the bare minimum Kotlin setup function
private fun ssl():SSLServerSocketFactory {
val password = "MYPASSWORD".toCharArray()
val kmf = KeyManagerFactory.getInstance("SunX509")
val tmf = TrustManagerFactory.getInstance("SunX509")
val sslContext = SSLContext.getInstance("TLS")
// initialise the keystore
KeyStore.getInstance("JKS").let { ks->
FileInputStream("lig.keystore").use {
ks.load(it, password)
}
kmf.init(ks, password)
tmf.init(ks)
}
// setup the HTTPS context and parameters
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null)
return sslContext.serverSocketFactory
}
ssl().createServerSocket().use { serverSocket ->
serverSocket.reuseAddress = true
serverSocket.bind(InetSocketAddress(port))
logger.info { "WebServer ready and listening on ${serverSocket.localPort}" }
But I'm having trouble how to finish it off: Do I need to make a lig.keystore file? Can this even be done without installing certs on the client's browser?
There are two common approaches to getting a secure connection between a client (browser) and server via HTTPS:
You can obtain SSL certificate for the server that is signed by a Root Certification Authority (CA) that is trusted by the user's web browser by default.
You can generate a self-signed SSL certificate, and have the user import it into their web browser as a trusted cert.
What you have done so far seems to be to generate a server-side keystore with a self-signed cert in it and (more or less) configured the Kotlin server to use it. The problem is the client (browser). There is no safe way to get the browser to trust the self-signed cert without the involvement of the user or the user's sysadmin. (Safe ... as in safe for the user!)
And no legitimate CA should ever issue an SSL cert for "localhost"; e.g. https://www.ssl2buy.com/wiki/how-to-get-ssl-certificate-for-web-applications-that-runs-on-localhost
Impasse.
OK, so lets step back. The purpose of using HTTPS / SSL is to ensure that:
The user's web browser is talking to the correct server, and not some other server that is impersonating it.
The connection between the browser and the server is encrypted so that no third party can snoop on the traffic.
But you are trying to do this for a localhost connection. The localhost IP address is a loopback address. Unless the OS kernel is compromised, you are guaranteed that network packets sent via a loopback connection will not leave the host.
You can dismiss the "impersonation" problem. Assuming that the user's machine has not been compromised, nobody else can launch a "fake" server on the user's machine.
You can dismiss the "snooping" problem. Assuming that the user's machine has not been compromised:
The packets won't go off-host, so they can't be snooped on any "external" networks.
The only person who can "snoop" the packets on the loopback network is the user him / herself.
So, the solution is simple. Use "http" for your "localhost" connection. It should be secure ... assuming that the user's machine has not been compromised.
Note: if the user's machine has been compromised, then the bad guys have other ways to intercept the traffic that SSL won't protect against.
Another specific case:
I'm facing a web app from https that would load local data at http://localhost
Safari web browser blocks because of unsecure communication (http) in a secure flow (https).
This behavour could be discussed, but in that case self signed certificate for localhost would help., even with a warning from Safari browser.

HTTPS through HTTP proxy

I have service which works like a proxy, you can get web pages through it. For example via telnet
GET http://example.com HTTP/1.1
Host: example.com
But if I want download https page I should do the following
GET https://example.com HTTP/1.1
Host: example.com
Https-Header: true
And I want to write scala client for this service using apache http client, using service like a proxy host.
private val DefaultProxy = new HttpHost("service host", port)
private val DefaultClient =
HttpClientBuilder.create().
setProxy(DefaultProxy).
build()
I can successfully download http pages, but when I try to download https pages, apache client makes CONNECT request to the proxy, and it response with error, cause service can operate only with GET requests.
How can I make apache client work with https pages like with http, that's mean send GET request to proxy, not CONNECT?
To download an https webpage in the same way than an http one with telnet you need to establish the ssl/tls connection first:
openssl s_client -connect www.somesite:443
[watch the ssl certificate details scroll by]
GET /index.html HTTP/1.1
Host: www.somesite
Example from https://www.bearfruit.org/2008/04/17/telnet-for-testing-ssl-https-websites/
For scala maybe that can help you : https://github.com/scalaj/scalaj-http
HTTPS is HTTP over SSL/TLS so you need something to establish the SSL/TLS secure tunnel to the website, then you can send your HTTP request.
I find out a solution.
I write custom HttpRoutePlanner which always provide not secure route, and then Apache client work with https link like with http link, there is a HttpRoutePlanner code
private def routePlanner(proxy: HttpHost) = new HttpRoutePlanner() {
def determineRoute(target: HttpHost ,
request: HttpRequest,
context: HttpContext) = {
new HttpRoute(target, null, proxy, false)
}
}

Mutual Auth on Glassfish, Connection Interrupted

I have a Glassfish instance, 3.1.2.2, with 4 HTTP listeners. Here are the relevant data points:
admin-listener : default admin 4848
Works fine
http-listener-1 : default http 8080
Works fine
http-listener-2 : ssl (server auth) 8181
Works fine
http-listener-3 : ssl (mutual auth) 8282
Server cert is retrieved but then a the connection is 'interrupted' no errors in the logs
Obvious configuration info:
keystore.jks has a self signed certificate with the correct CN (CN=ServerName), 'selfcert'.
selfcert is the named certificate for both ssl listeners
cacerts.jks has a copy of the client issued CA
The web browser has a client certificate signed by the CA
ports are open in the firewall
Web Application is using SpringSecurity, the x509 tag, and has been successfully deployed on other platforms
I've scoured SO and the search engines to no avail. Any guidance would be appreciated.
Thanks,
This seems to be an issue/bugenter link description here that was documented and will be addressed in Glassfish 4

How to verify the correctness of configuring mutual authentication (client certificate, server certificate) Java EE?

I am trying to write a simple application to understand the basics of configuring authentication based on client and server certificates.
I have done everything as it is explained in jave ee 5, java ee 6 tutorials
http://docs.oracle.com/javaee/6/tutorial/doc/glien.html
Opened example from javaee tutorials hello basicauthorization (just simple servlet which can be accessed only after authentication) and then reconfigured it for client certificates instead of basic authorizations
Configured web.xml
Configured glassfish-web.xml
Generated client certificate
Imported client certificate so that the server would trust it.
The problem:
When I deploy my application, and follow the link, corresponding to the application, I get a message from glassfish server HTTP Status 400 - No client certificate chain in this request".
So, it seems, that the client (browser) doesn't send the certificate with the request
I tried adding the .cer certificate to Chrome, firefox, internet explorer and they are added (no error is displayed), but as you see that doesn't help.
So, the question is:
How to get the access to my application through the web browser having client .cer certificate?
You can debug ssl on the server-side by adding (somewhere in Glassfish) system properties:
-Djavax.net.debug=all
see this page for details.
You can also debug from the client perspective using openssl tool:
openssl s_client -connect host:port -debug -msg
you should see something like this:
...
Acceptable client certificate CA names
/C=PL/O=company/OU=xx/CN=host/emailAddress=email#example.com
/C=PL/O=company/OU=xx/CN=ca/emailAddress=email#example.com
---
SSL handshake has read 2536 bytes and written 116 bytes
...
your problem is probably related to bad truststore configuration on the server-side - server sends some Acceptable client certificate CA names (or no at all), but browser doesn't have anything to offer - it doesn't have any private key+certificate issued by acceptable ca.

Categories