What does Google Chrome Developer Console “GDPR: GTM is enabled!” mean?

I have just opened the Google Chrome Developer Console when browsing a media channel web site and saw the following information:

Google Chrome Developer Console GTM is enabled

What I managed to find out:

  • GTM seems to be Google Tag Manager
  • SATI is an acronym for an agency/company that studies Internet traffic

What does this information actually mean, especially the green flags?

.net – Get Service Name running the Console Application in C#

I have a console application that I want to run as a service.The console application reads the data from MSMQ (Each data point in MSMQ has its unique ID) ,if any and proces it accordingly. I am creating multiple instances of the console application in services.msc so that the data in the MSMQ get processed parallelly . Is there any way to get the Service Name that is processing a particular ID data in the console application itself as I need to log the details of which service picks up which data point or task based on ID.

public key – Generating Bitcoin address from private key in browser console

If JavaScript is your language of choice you might be interested in bcoin – the bitcoin full node implementation and modular library written in JS. It’s designed for use in nodejs environments but can be compiled for the browser as well.

This guide in particular walks you through the process: https://bcoin.io/guides/webapp.html

Please note that web browsers are insecure environments for cryptography and especially cryptocurrency, this guide is based around public keys and testnet addresses to avoid any real risk. If you try to manage private keys in a browser’s JS environment you need to be extremely careful (use an offline computer if possible, no “chrome extensions” etc)

keyboard shortcuts – Can Spotify information (song information – ‘liked’ or not) be escaped by the console logs rather than going through their web API?

I use a macOS program called AnyBar https://github.com/tonsky/AnyBar that displays different colored indicator dots based on what criteria you give it and I need to configure it.

I currently use it to notify me a trackpad gesture shortcut from a mac program called bettertouchtool (BTT) has went through (because it doesn’t always go through and I don’t want to go and check if it did).

I use AnyBar for finetuning Spotify playlists in the background (liking, deleting, moving to playlists, whatever) when watching something (because it gets really old looking at spotify gui.

This is how it looks when a gesture goes through, enough to notify me, but not distract from what I’m watching.

enter image description here

I’d like to do something more advanced and have it automatically change color lights depending on if the currently spotify song is ‘liked’ already or not (my system for recognizing songs I’ve played before).

I’m going to pay for help on freelancer or fiverr most likely because I don’t know coding but want to know what I’m pitching to them, will the info ‘liked’ state have to come from the web api and then work with a script, (I’ve used python3 scripts well in the past) or can I get it from console logs (which would make other applications easier too).

Need Help about Console in Bitcoin Core

Running Bitcoin Core (bitcoind or bitcoin-qt) already means running a node.
You don’t need to set it up.

The addnode function is used to manually add a connection to another node.
This is not something necessary, unless you have specific reasons to connect to a particular node (e.g. a node you trust).
This function does not return any object (although executed successfully), which is why get null in return.

getnodeaddresses returns a random subset of node addresses known to your node.

As for the RPC methods, generateprivkey does not exist, while the error for createrawtransaction is probably due to a wrong input format (you are missing the squared brackets in the second object)
The correct format is:

({"txid":"id","vout":n},...) ({"address":amount},{"data":"hex"},...)

Also note that you won’t be able to create a transaction without having the corresponding keys in your wallet.

boot – Unable to use ttyUSB0 as console

I have a server (Ubuntu 20.04.1 Kernel 5.4.0-42-generic) that is meant to be headless and able to be remote rebooted (with encrypted root) I have a USB to Serial adapter in the machine and was wanting to use this as a console at boot time to enable headless/remote unlocking of the encrypted root.

I am able to successfully connect to the console once host is booted after enabling serial-getty@ttyUSB0.service so the adapter works and is cabled correctly.

I have added “console=tty0 console=ttyUSB0” to GRUB at boot time but this appears to be outright ignored by the kernel.

$ dmesg | grep tty
(    0.000000) Command line: BOOT_IMAGE=/vmlinuz-5.4.0-42-generic root=/dev/mapper/host--vg-host_root--lv ro ipv6.disable=1 console=tty0 console=ttyUSB0
(    0.056872) Kernel command line: BOOT_IMAGE=/vmlinuz-5.4.0-42-generic root=/dev/mapper/host--vg-host_root--lv ro ipv6.disable=1 console=tty0 console=ttyUSB0
(    0.115389) printk: console (tty0) enabled
(    0.458997) 00:05: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A
(   54.731750) usb 1-1.5: pl2303 converter now attached to ttyUSB0

I have tested using “console=tty0 console=ttyS0” which appears to work though I have no serial port connected to that interface so unable to verify and would prefer to have this working via USB rather than needing to source a port header

$ dmesg | grep tty
(    0.000000) Command line: BOOT_IMAGE=/vmlinuz-5.4.0-42-generic root=/dev/mapper/host--vg-host_root--lv ro ipv6.disable=1 console=ttyS0 console=tty0
(    0.056348) Kernel command line: BOOT_IMAGE=/vmlinuz-5.4.0-42-generic root=/dev/mapper/host--vg-host_root--lv ro ipv6.disable=1 console=ttyS0 console=tty0
(    0.115326) printk: console (tty0) enabled
(   26.469014) printk: console (ttyS0) enabled
(   40.385803) 00:05: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A
(   51.949414) tty tty40: hash matches
(   87.762789) systemd(1): Created slice system-serialx2dgetty.slice.
(   91.428703) usb 1-1.5: pl2303 converter now attached to ttyUSB0

My current theory is that the kernel has not been compiled with CONFIG_USB_SERIAL_CONSOLE enabled.

So my questions…

  1. Is my theory correct and I am unable to do this with current kernel build?
    1a) If so is there any way to request this be added in future kernel builds?
  2. Is there something I am missing that would get this to work?

Any assistance would be appreciated.
Cheers

Console Snake Game C++ – Code Review Stack Exchange

I’ve tried to make a snake game. I think it works. But I really need your help to improve the code in terms of (readability – maintainability – efficiency, and so on). Is my code spaghetti? Any criticism is appreciated.

Here’s what’s done:

#include <iostream>
#include <vector>
#include <conio.h>
#include <cassert>


const int height = 25;
const int width = 90;
char board(height)(width);
bool snake_pos(height)(width);
std::vector<std::pair<int, int>> body; // body(0) head position
int cnt = 1;

void reset_board();
void draw_board();
void handle_input();

int foodX, foodY;

void reset_board() {
    for (int i = 0; i < width; i++)
        board(0)(i) = '#';
    for (int i = 1; i < height; i++) {
        for (int j = 0; j < width; j++) {
            // is border?
            if (j == 0 || j == width - 1) {
                board(i)(j) = '#';
            }
            else {
                board(i)(j) = ' ';
            }
        }
    }
    for (int i = 0; i < width; i++) {
        board(24)(i) = '#';
    }
    board(body(0).first)(body(0).second) = 'O';
    for (int i = 1; i < body.size(); i++)
        board(body(i).first)(body(i).second) = 'o';
    for (auto x : body)
        snake_pos(x.first)(x.second) = true;
        
    board(foodX)(foodY) = 'X';
}

void draw_board() {
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            std::cout << board(i)(j);
        }
        std::cout << 'n';
    }
}

int rand(int a, int b) {
    return a + rand() % (b - a + 1);
}

void food() {
    int x = rand(1, 23);
    int y = rand(1, 88);
    // while food pos is part of the snake
    while (snake_pos(x)(y)) {
        x = rand(1, 23);
        y = rand(1, 88);
    }
    foodX = x;
    foodY = y;
}

#define KEY_UP 'w'
#define KEY_DOWN 's'
#define KEY_LEFT 'a'
#define KEY_RIGHT 'd'

bool game_over(int x, int y) {
    // check if head ate body
    for (int i = 1; i < body.size(); i++) {
        if (std::make_pair(x, y) == body(i))
            return true;
    }
    return false;
}

bool valid_move(char key) {
    // check if move is not in opposite direction 
    // 0, 1, 2, 3 (left, right, up, down) respectively
    if (cnt == 3 && key == KEY_UP)
        return false;
    if (cnt == 2 && key == KEY_DOWN)
        return false;
    if (cnt == 1 && key == KEY_LEFT)
        return false;
    if (cnt == 0 && key == KEY_RIGHT)
        return false;
    switch (key) {
    case KEY_LEFT:
        cnt = 0;
        break;
    case KEY_RIGHT:
        cnt = 1;
        break;
    case KEY_UP:
        cnt = 2;
        break;
    case KEY_DOWN:
        cnt = 3;
        break;
    default:
        assert(false);
    }
    return true;

}

bool food_eaten() {
    return body(0).first == foodX && body(0).second == foodY;
}

void handle_input() {
    char key = _getch();
    
    
    if (key == KEY_UP && valid_move(key)) {
        
        std::pair<int, int> prev = body(0);

        body(0).first--;
        if (body(0).first == 0)
            body(0).first = 23;
        if (game_over(body(0).first, body(0).second)) {
            std::cout << "Game is overn";
            exit(0);
        }
        if (food_eaten()) {
            board(foodX)(foodY) = ' ';
            // add tail 
            body.push_back({ body.back().first + 1, body.back().second });
            reset_board();
            // draw new food
            food();
        }

        
        for (int i = 1; i < body.size(); i++) {
            std::pair<int, int> tmp = body(i);
            body(i) = prev;
            prev = tmp;

        }
        
    }
            
        
    else if (key == KEY_DOWN && valid_move(key)) {
        
        std::pair<int, int> prev = body(0);
        body(0).first++;
        if (body(0).first == 24)
            body(0).first = 1;
        if (game_over(body(0).first, body(0).second)) {
            std::cout << "Game is overn";
            exit(0);
        }
        if (food_eaten()) {
            board(foodX)(foodY) = ' ';
            body.push_back({body.back().first - 1, body.back().second});
            reset_board();
            food();
        }
        
        for (int i = 1; i < body.size(); i++) {
            std::pair<int, int> tmp = body(i);
            body(i) = prev;
            prev = tmp;

        }
        
            
    }
    else if (key == KEY_LEFT && valid_move(key)) {
        if (cnt == 1) return;
        cnt = 0;
        std::pair<int, int> prev = body(0);
        body(0).second--;
        if (body(0).second == 0) {
            body(0).second = 88;
        }
        if (game_over(body(0).first, body(0).second)) {
            std::cout << "Game is overn";
            exit(0);
        }
        if (food_eaten()) {
            board(foodX)(foodY) = ' ';
            body.push_back({ body.back().first, body.back().second + 1 });
            reset_board();
            food();
        }
        
        for (int i = 1; i < body.size(); i++) {
            std::pair<int, int> tmp = body(i);
            body(i) = prev;
            prev = tmp;

        }
            
    }
    else if (key == KEY_RIGHT && valid_move(key)) {
        std::pair<int, int> prev = body(0);
        body(0).second++;
        if (body(0).second == 89) {
            body(0).second = 1;
        }
        if (game_over(body(0).first, body(0).second)) {
            std::cout << "Game is overn";
            exit(0);
        }
        if (food_eaten()) {
            board(foodX)(foodY) = ' ';
            body.push_back({ body.back().first, body.back().second - 1 });
            reset_board();
            food();
        }
        
        for (int i = 1; i < body.size(); i++) {
            std::pair<int, int> tmp = body(i);
            body(i) = prev;
            prev = tmp;

        }
            
    }
    system("cls");
    reset_board();
    draw_board();
    


        
}
int main()
{
    food();
    // initial snake 
    snake_pos(4)(81) = snake_pos(4)(80) = snake_pos(4)(79) = snake_pos(4)(82) = true;
    body.push_back({ 4, 82 });
    body.push_back({ 4, 81 });
    body.push_back({ 4, 80 });
    body.push_back({ 4, 79 });
    while (true) {
        handle_input();
    }
    

    return 0;

}

Using Google Authenticator for SSH and Console Connections to Your VPS

Using Google Authenticator for SSH and Console Connections to Your VPSIn this tutorial, we’re going to show you how to setup your VPS to use two-factor authentication for both normal SSH connections and console logins with Google Authenticator.

“One factor” authentication is either “something you know” or “something you have”. For example, logging in with a password is “something you know” and so that is single-factor authentication. Two factor authentication requires both something you know and something you have. A common means to achieve this is by using SSH keys. You must have both the SSH private key file and know the passphrase to unlock that SSH private key. If someone looked over your shoulder and saw you type your SSH key passphrase, or if someone stole your SSH private key file, neither by themself would be sufficient. They would need to know both your passphrase and have your key file to be successful.

The problem with SSH private keys is that you must carry the file around with you. If you’re always logging in from home or from one laptop, that’s fine, but what if you want to login from a friend’s house, from work, or from the library? Either you have to carry your private key around on a USB or put it on cloud storage, neither of which is optimal. Is there a way we can require “something you have” without needing to have access a file? Yes, with Google Authenticator.

Another problem is console access. Your VPS provider provides console access as a way for you to access your VPS if you can’t get in via ssh (for example, if you munge the firewall rules).  Here you cannot use an SSH key file.  This means that access to all of your VPSes with that provider are dependent on whatever password you setup for the provider’s control panel. Worse, that password is sometimes emailed to you in clear text! This also means that if someone can get ahold of your email, then they can do a password reset, recover your control panel password, and compromise all of your VPSes. However, we can plug this hole, too, with Google Authenticator.

Instead of having a key file, in this system your “what you know” is the Google Authenticator app. Every 30 seconds, the Authenticator displays a new 6-digit number. Through some crypto mathematical wizardry, your VPS knows what this number is. When you login, you’re prompted to enter this number after entering your Unix password.

To be clear, no one else can easily guess this number, and the number is only good for 30 seconds. So even if someone did see your number, they only have 30 seconds to try to reuse it. You can even defeat that by rate-limiting logins so that the number can only be used once.

I’ll be using a brand spanking new Debian 10 VM I’ve named fortress.lowend.party. After imaging it, I’ll setup the PAM module for Google Authenticator and reconfigure sshd. PAM stands for Pluggable Authentication Module. It allows you to setup requirements for any kind of authentication – login, sudo, etc. In this case, we’re going to setup an sshd authentication that requires both the Unix password and Google Authenticator.

apt-get update
apt-get -y install libpam-google-authenticator

Google Authenticator requires time sync, so let’s make sure our VPS always has the proper time. We’ll use ntpd (the Network Time Protocol daemon) for this purpose.

apt-get -y install ntp
systemctl start ntp
systemctl enable ntp

NTP is timezone-agnostic, but if you haven’t done so, you might want to set your timezone properly here.

dpkg-reconfigure tzdata

Or if you know the name of the timezone you want to use:

timedatectl set-timezone America/Los_Angeles

Now I’ll switch to a user I’ll use for login (raindog308) and run the Google Authenticator setup.

raindog308@fortress:~$ google-authenticator
Do you want authentication tokens to be time-based (y/n) y

Say yes to this question.  Now a pretty cool QR scan code will print out, in your terminal, for you to scan with your phone:

Let’s setup the app while the QR code is still on your screen.

In my case I’m using an iPhone. I’ve installed the free Google Authenticator app from the App Store and started it.

Tap Begin Setup (at bottom).

Tap Scan barcode.

Give permission to access your camera. Then hold your phone up to your screen so the QR code appears in the green box. Moments later, the app will register your authenticator.

Now go back to your terminal session. Copy and save the secret key, verification code, and emergency codes in some secure place. An entry in whatever password safe you use is an excellent choice.

Now finish answering the questions:

Do you want me to update your "/home/raindog308/.google_authenticator" file? (y/n) y

Say yes!

Do you want to disallow multiple uses of the same authentication
token? This restricts you to one login about every 30s, but it increases
your chances to notice or even prevent man-in-the-middle attacks (y/n)

Your choice, but saying yes is more secure.

By default, a new token is generated every 30 seconds by the mobile app.
In order to compensate for possible time-skew between the client and the server,
we allow an extra token before and after the current time. This allows for a
time skew of up to 30 seconds between authentication server and client. If you
experience problems with poor time synchronization, you can increase the window
from its default size of 3 permitted codes (one previous code, the current
code, the next code) to 17 permitted codes (the 8 previous codes, the current
code, and the 8 next codes). This will permit for a time skew of up to 4 minutes
between client and server.
Do you want to do so? (y/n)

You shouldn’t really need this. Say no.

If the computer that you are logging into isn't hardened against brute-force
login attempts, you can enable rate-limiting for the authentication module.
By default, this limits attackers to no more than 3 login attempts every 30s.
Do you want to enable rate-limiting? (y/n)

Your choice but yes is the more secure choice.

Now open a new shell and su or sudo to root. You’re going to keep this second session open so that if anything is fumbled while setting up Google Authenticator, you have a fallback session and can quickly fix things.

Edit /etc/pam.d/sshd and add the following two lines:

auth required pam_unix.so no_warn try_first_pass
auth required pam_google_authenticator.so

These lines mean mean “Unix password required, Google Authenticator required”.

Now edit /etc/ssh/sshd_config and change as follows:

UsePAM yes
ChallengeResponseAuthentication yes

This will require Google Authenticator for all users. Note that Google Authenticator is not required for SSH keys. So the requirements to login are either (1) you have your private ssh key file and know its passphrase, or (2) you enter the Unix password and enter the proper Google Authenticator 6-digit code. Note that root logins are special and are handled by the PermitRootLogin directive in sshd_config. Normally, PermitRootLogin should either be set to “no” or “prohibit-password” to require SSH keys.  We’ll fix console logins later in this tutorial.

Restart sshd:

systemctl restart ssh

Now let’s try logging in. Open a new terminal so you can use the root session as a fallback.

$ ssh raindog308@fortress.lowend.party
Password:
Verification code:
Linux fortress.lowend.party 4.19.0-8-amd64 #1 SMP Debian 4.19.98-1 (2020-01-26) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
raindog308@fortress:~$

At the “Verification code” prompt, I entered the six-digit code on my Google Authenticator app. We are officially party rockin’!

To require Google Authenticator for console logins, you probably want to configure Google Authenticator for the root account so you can login as root on the console. Just repeat the google-authenticator steps above to generate the QR code and register it with your app. You’ll have two entries in your app:

Now edit /etc/pam.d/login and add this line:

auth required pam_google_authenticator.so

This is the same as one of the entries we put in /etc/pam.d/sshd.

Now if you go to your provider’s panel and try to login on the console (as root) you’ll find you’re required to use Google Authenticator.

Debian GNU/Linux 10 fortress.lowend.party ttyS0

fortress login: root
Password:
Verification code:
Last login: Wed May 13 16:20:09 PDT 2020 on ttyS0
Linux fortress.lowend.party 4.19.0-8-amd64 #1 SMP Debian 4.19.98-1 (2020-01-26)4

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
root@fortress:~#

In the user’s home directory you’ll find a file called .google-authenticator. If you were to nuke your VPS, setup Google Authenticator again, and then place this file back in the user’s home directory (with proper ownership and mode 0600), Google Authenticator would work for that user.

If your phone was lost or for some other reason you needed to reinstall the Google Authenticator app, you would select “Manual entry” in the app and then enter both the account and the key. That was the part that said:

Your new secret key is: BY7QKIUJR2WLPRKT53UR5VPKZU

You did save that key somewhere safe…right?

The key also appears as the first line in the .google-authenticator file. Here, for example, is my .google-authenticator file on fortress.lowend.party:

BY7QKIUJR2WLPRKT53UR5VPKZU
" RATE_LIMIT 3 30 1589413925
" TOTP_AUTH
36720568
35095323
92648133
21906908
71813960

To simulate loss of my phone, I deleted the raindog308@fortress.lowend.party from my Google Authenticator app:

Then I hit the “+” button in the upper right and selected Manual entry:

I typed in my name for the account (raindog308@fortress.lowend.party) and then laboriously entered the key (BY7QKIUJR2WLPRKT53UR5VPKZU):

The entry was thus recreated:

I was then able to login again as raindog308 with Google Authenticator.

 

 

 

raindog308

I’m Andrew, techno polymath and long-time LowEndTalk community Moderator. My technical interests include all things Unix, perl, python, shell scripting, and relational database systems. I enjoy writing technical articles here on LowEndBox to help people get more out of their VPSes.