The Idea

Why I implement this application.

Traditional way to connect to SSH server

coldnew@gentoo ~ $ ssh coldnew@192.168.20.100
The authenticity of host '192.168.20.100 (192.168.20.100)' can't be established.
ECDSA key fingerprint is SHA256:izC+HeDEm/u1FcCzpM+aBgpbuGlrGD1HkMnwLVkS+ac.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.20.100' (ECDSA) to the list of known hosts.
Password:

Connect to SSH server without password

  • You can use ssh-copy-id to make ssh without password

    coldnew@gentoo ~ $ ssh-copy-id ~/.ssh/id_rsa.pub coldnew@192.168.20.100
    Password:
    
  • Now it's no need to type any password to login

    coldnew@gentoo ~ $ ssh coldnew@192.168.20.100
    Warning: Permanently added '192.168.20.100' (ECDSA) to the list of known hosts.
    coldnew@pc ~ $
    

Use password vs without password

  • password
    • Your server may not be secure
    • Brute force attack
  • without password
    • You need to setup key first to let user login
    • System may be not easy to mantain but more secure

The Soultion: Google Authenticator

g2fa-auth-setup.gif

But…

What if we don't trust Google ?

Google said: Don't be evil

Dontbeevil.jpg

Eat you own dogfood

eat.jpg

Here's what I have done

ssh1.png

So…

Let's talk about telegram-authenticator

What's telegram ?

  • Is a brand new instant-messanger application
  • Client is open source, but server isn't

    stats-msg-tg.jpg

Telegram support BOT

tbot.png

How to create telegram bot ?

Add botfather to your channel

b1.png

Use commands to control your own bot

b2.png

Create new bot

b3.png

Create new bot

b4.png

Now we know our bot token

239551761:AAFRfD7iN-YTC1o5od8y0IMnFbg-fWdkG4I

A simple guide on botAPI

And you'll know how to write a bot

Telegram's botAPI

Add bot to channel

b5.png

Add bot to channel

b6.png

Add bot to channel

b7.png

Getting updates

  • You cant get update from
https://api.telegram.org/bot${TOKEN}/getUpdates
  • So… our bot token is
239551761:AAFRfD7iN-YTC1o5od8y0IMnFbg-fWdkG4I
  • And the bot message can get from
https://api.telegram.org/bot239551761:AAFRfD7iN-YTC1o5od8y0IMnFbg-fWdkG4I/getUpdates

Here's what we get after you type something

{ "ok":true,
   "result":[ {
         "update_id":556578430,
         "message":{
            "message_id":2,
            "from":{
               "id":81660412,
               "first_name":"Yen-Chin",
               "last_name":"Lee",
               "username":"coldnew" },
            "chat":{
               "id":81660412,
               "first_name":"Yen-Chin",
               "last_name":"Lee",
               "username":"coldnew",
               "type":"private" },   "date":1473738006,  "text":"test" } }, ] }

The chat_id is the room id

  • chat_id: 8166042
{"update_id":556578430,
 "message":{
     "message_id":2,
     "from":{
         "id":81660412,
         "first_name":"Yen-Chin",
         "last_name":"Lee",
         "username":"coldnew" },
     "chat":{
         "id":81660412,
         "first_name":"Yen-Chin",
         "last_name":"Lee",
         "username":"coldnew",
         "type":"private" },   "date":1473738006,  "text":"test" } }

Send message to bot channel

  • Now you find the chat_id, you can send message to specific channel
  • Use following url to do it
https://api.telegram.org/bot${TOKEN}/sendMessage
  • So… in this example, we has this url
https://api.telegram.org/bot239551761:AAFRfD7iN-YTC1o5od8y0IMnFbg-fWdkG4I/sendMessage
  • You need to add parameter to specify chat_id and text
{"chat_id": "81660412",
 "text": "Hello telegram bot"}

Let's try it with curl command

curl -s \
     -X POST \
     https://api.telegram.org/bot239551761:AAFRfD7iN-YTC1o5od8y0IMnFbg-fWdkG4I/sendMessage \
     -d text="Hello telegram bot" \
     -d chat_id=81660412

tx1.png

Writing pam_module

What's pam ?

  • PAM (Pluggable Authentication Modules)
  • Use for user authentication in any modern linux distribution


  • For more info on how to write pam_module, please see

A simple hello world example

  • pam_hello.c
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <security/pam_modules.h>
#include <security/pam_ext.h>

PAM_EXTERN int pam_sm_authenticate(pam_handle_t* pamh, int flags, int argc,
                                   char const** argv) {
        pam_info(pamh, "Hello there!!");
        return PAM_IGNORE;
}

PAM_EXTERN int pam_sm_setcred(pam_handle_t* pamh, int flags, int argc,
                              char const** argv) {
        return PAM_SUCCESS;
}
  • Compile with
gcc pam_hello.c -fPIC -lpam -shared -o pam_hello.so

Move the pam_hello.so to it's place

  • In my system, it's /lib/security

    sudo mv pam_hello.so /lib/security/
    
  • Modify /etc/pam.d/sshd

    auth       required     pam_hello.so
    
  • Modify /etc/ssh/sshd_config

    ChallengeResponseAuthentication yes
    

Now, let's test it

  • Remember to restart sshd first

    sudo systemctl rstart sshd
    
  • Test ssh login

    coldnew@pc ~ $ ssh coldnew@192.168.20.100
    Password:
    Hello there!!
    coldnew@gentoo ~ $
    

The Project

telegram-authenticator

It's in alpha but almost worked

How to use it

  • Installed it like what we installed pam_hello.so
  • Move the lib to /lib/security

    sudo mv pam_telegram_authenticator.so /lib/security/
    
  • Modify /etc/pam.d/sshd

    auth       required     pam_telegram_authenticator.so
    
  • Modify /etc/ssh/sshd_config

    ChallengeResponseAuthentication yes
    

Use userspace application to save bot info

coldnew@gentoo ~ $ telegram-authenticator
Please enter your telegram bot token:
239551761:AAFRfD7iN-YTC1o5od8y0IMnFbg-fWdkG4I
Please type '/start' to your telegram bot
Waiting for user type '/start' in telegram bot channel

Find chat_id: 81660412

Do you want to write setting to your config? (y/n) y

After your setup, this application will send info to telegram

cx1.png

And … you'll get this result

ssh1.png

The missing part

A little guide on json-c

In this project, we use json-c

  • To parse json info
  • Mix with curl to send json info

How to use json-c

  • Our target
{ "ok":true,
  "result":[ { "update_id":556578430,
               "message":{ "message_id":2, "chat":{ "id":81660412 }  "text":"test" }}]}
  • Parse result
json_object *root = json_tokener_parse(DATA);
json_object *body;
json_object_object_get_ex(root, "result", &body);

// print it
printf("result: %s\n", json_object_to_json_string(body));

How to user json-c on array

{ "result":[ {"message":{ "message_id":2, "chat":{ "id":81660412 }  "text":"test" }}]}
json_object *root = json_tokener_parse(DATA);
json_object *body;
json_object_object_get_ex(root, "result", &body);
int arraylen = json_object_array_length(body);
json_object *jvalue;
for (int i = 0; i < arraylen; i++) {
        jvalue = json_object_array_get_idx(body, i);

        struct json_object *jchat;
        json_object_object_get_ex(jmessage, "chat", &jchat);

        struct json_object *jchat_id;
        json_object_object_get_ex(jchat, "id", &jchat_id);
}

Thank You