Background

One day in business, I wanted to continuously monitor the scan results of an environment’s nmap. If a trigger condition is met, an alert should be sent, preferably notifying myself. Regarding the choice of notification terminal, email didn’t feel right, and SMS was unrealistic. At that time, I thought of ServerChan, but unfortunately the free version could no longer meet my needs. I hoped the notification method could be through an app.

After searching, I found that many V2EX users recommended Bark. I decided to give it a try. After a brief understanding, I found that Bark mainly targets iOS-related push notification services and does not have an Android client. If you want to support multiple clients, you might need to find another solution.

Since it’s a personal toolkit, it already meets my needs.

Directly check the Bark documentation, mainly tested the APNS direct push and encrypted push parts, to compare the differences between the two curl POST methods. After APNS notification, the Bark app displays the message count in the upper right corner and a popup message. For encrypted direct push, only a popup message appears without the numeric badge.

Implementation

To quickly implement the current functionality, after testing, I directly chose the encrypted curl POST method. Below is the key part of my implementation:

Keys and related privacy parts have been redacted.

#!/bin/bash

# function: bark uses curl to push encrypted messages, sending messages from the server to the iOS bark app via shell script
# author: yh
# last update: 2023.8.30

## https://bark.day.app/#/tutorial
function encrypt_msg() {
    # bark key
    deviceKey='AYXhqtRXXXXXXXXXXXX'
    # push payload
    json='{"body": "'${body1}'", "title": "'${title1}'", "group": "work", "sound": "birdsong"}'

    # Must be 16 characters
    key='VS3Nxxxxxxxxxx77'
    # IV can be randomly generated, but if random, it needs to be passed in the iv parameter.
    iv='aizJxxxxxxxxxx7x'

    # OpenSSL requires the input Key and IV to be hex-encoded.
    key=$(printf $key | xxd -ps -c 200)
    iv=$(printf $iv | xxd -ps -c 200)

    ## When editing JSON in vscode, converting to ciphertext may cause Decryption Failed issues
    ## Reference: https://github.com/Finb/Bark/issues/192    add tr -d '\n'
    ciphertext=$(echo -n $json | openssl enc -aes-128-cbc -K $key -iv $iv | base64|tr -d '\n')
    # echo $ciphertext
    # Ciphertext may contain special characters, so remember to URL-encode it.
    curl --data-urlencode "ciphertext=$ciphertext" https://api.day.app/$deviceKey

}

function check_info () {
    openport_lines=`/usr/bin/nmap -p 1-65535 -Pn --open 21.XXXXX 21.XXXXX --host-timeout 60  -vvv|grep 'open\|PORT'|wc -l`
    if [ $openport_lines -gt 0 ]; then
        body1='XXnmap issue'
        title1='Alert'
        encrypt_msg
    else
        echo "fine" > /dev/null 2>&1
    fi
}

check_info

The only part to mention separately is the encryption and transcoding of the JSON content:

  ciphertext=$(echo -n $json | openssl enc -aes-128-cbc -K $key -iv $iv | base64|tr -d '\n')

When editing code in VSCode, testing on Linux could successfully send messages with a return code of msg 200, but the phone always showed a Decryption Failed error. Initially, I thought it was due to the body content being too long or field restrictions from the official side. After comparing and testing for a long time, I found it was actually my own issue.

Combining APNS and related push encryption tutorials, it can be optimized further in the future.