Friday, November 18, 2016

Securing Your Server: Part 1 - Fail2Ban and SSH Keys

On Linux, viruses tend not to occur as frequently as Windows. However, Linux is not exempt from security threats. In Linux, the threat tends to occur instead in the form of SSH/telnet password-guessing bots. The situation is so bad that there are even bots that break into servers and set up proper security systems. There are some easy steps that you can take to avoid getting hacked.

1. Don't Use Telnet
Telnet is old, outdated, and much easier to break into than SSH. If you really need telnet for some reason, you can try blocking access from IP's other than localhost and tunneling the connection through SSH.

2. Don't Use A Common Login
These bots will usually start by trying common logins - such as the default login for the pi account on Raspberry Pi. If you use one of these logins, you are likely to be hacked shortly after exposing the SSH port to the internet.

3. Use SSH Key Authentication and Disable SSH Password Authentication
SSH key authentication is much more secure than password authentication. It is based off of the RSA (or optionally DSA, although RSA is default/preferred) cryptographic algorithm. RSA is an asymmetric cipher - with one private key and one public key. The private key stays on the device connecting to the server and is used to sign data. The public key is used to verify this signature. This is significantly better than passwords because the private key is stored locally and is (usually) unique.

In order to create an SSH keypair, run the ssh-keygen command. This command will ask you to encrypt the key with a password for an extra layer of security (in case the device with the private key is compromised). By default, it will put the public key in .ssh/id_rsa.pub and the private key in .ssh/id_rsa in your home folder. To copy the public key to the server, run:
ssh-copy-id username@example.org
You can also save the file to .ssh/authorized_keys in your home folder on the server and set the permissions to 400 if you need to do this manually.

Now, you should be able to ssh using your ssh key.

Now that you have an SSH key set up, you can disable password authentication by editing /etc/ssh/sshd_config and adding these lines (although some may already be present by default):

RSAAuthentication yes
PubkeyAuthentication yes
PasswordAuthentication no

Now restart SSH, and your server should be better secured.

4. Use Fail2Ban
Whether or not you use password authentication, you should use Fail2Ban to protect your server. Fail2Ban is a python script which parses the server logs and blocks IP adresses that fail to log in a configurable amount of times. In Debian/Fedora/Ubuntu/most distros, it is available in repositories as fail2ban. You may also want to install sendmail for it to email you about failed logins.

Now open up /etc/fail2ban/jail.local

In it you want to set the following options:
  • backend - what method to use to tell Fail2Ban when the logs have been modified. If you are unsure, you can use backend = auto to leave the choice up to Fail2Ban
  • bantime - how long to keep an IP address banned (in seconds). This defaults to 600 (10 minutes) but I use 86400 (1 day) because some bots will try again as soon as they are unblocked.
  • maxretry - the number of failed login attempts in the specified amount of time to allow before banning. Defaults to 3.
  • findtime - the amount of time to keep track of failed login attempts in seconds. If you wait for this amount of time before attempting to login again, Fail2Ban will not ban you. Defaults to 600 (10 minutes).
Next, we want to block ssh. To do this, add the following config lines:

[ssh-iptables]
enabled  = true
filter   = sshd
action   = iptables[name=SSH, port=ssh, protocol=tcp]
#          mail-whois[name=SSH, dest=address@mailserver.com]
logpath  = /var/log/auth.log
maxretry = 5

Uncomment the mail-whois line and fill in your email address if you would also like Fail2Ban to send you info about the attacks (this needs sendmail installed).

Now, reload Fail2Ban and it will automatically protect your server!

Friday, August 19, 2016

What is SIMD?

SIMD - Single Instruction Multiple Data - is a technology to speed up math operations in a processor. It works by running the same instruction multiple times on different data.


However, this starts to bottleneck when the code involves branching. Most SIMD engines allow branching by allowing an instruction to be run conditionally - those not on the currently executing branch do nothing. So if there is one level of an if/else statement, only 50% of the units are active. Two levels? 25%. That is why SIMD is usually not used for branching intensive tasks such as decision trees.

One good example of SIMD is a GPU. Almost all current GPUs are groups of SIMD cores. Most CPU's have SIMD - Intel has dual 128-bit, AMD Bulldozer has 256-bit/dual 128-bit, and AMD Zen has 512-bit/dual 256-bit SIMD. Most mobile processors do too, however 1st gen Raspberry Pi's don't.

Thursday, August 18, 2016

Cryptocurrencies

Cryptocurrencies are digital currencies which derive their value from computing costs. The most well known cryptocurrency is Bitcoin. Nowadays, a Bitcoin is equivalent to nearly $600 - a big change from when they were equal to a cent.

Every cryptocurrency has two main components: a hashing algorithm and a blockchain distribution network. Bitcoin uses SHA-256, which is a common hashing algorithm on the internet. Cryptocurrencies keep a blockchain - a list of every transaction made. These are divided into blocks - each of which contains all of the transactions from a certain window of time. In Bitcoin, there is one block for every 10 minutes. Whenever someone makes a transaction, they first sign the transaction with an asymmetric cryptographic algorithm such as RSA and then broadcast the transaction to the network to be added to the next block. All nodes on the network keep their own copy of the blockchain and synchronize with other nodes.

But what stops people from changing the transaction record? And where do the bitcoins come from? The answer to both questions are the same. After a block has been created, people attempt to "mine" it. The process of mining involves first appending a random number to the beginning of the block and then hashing it. If the resulting hash is lower than a certain number, the network will grant the miner a certain amount of cryptocurrency - 25 bitcoins in the case of bitcoin (which is presently over $14 thousand). This number is called the difficulty. Every 2016 blocks, the difficulty is adjusted proportionally to the amount of time taken to mine the blocks with the goal of making it take 10 minutes per block.

Anyone can mine bitcoin with almost any computer, but it is difficult to become profitable. Because it will take an extremely large number of hashes on average in order to get a block, it will take a large amount of core-hours to mine a block on a CPU. At that point, the cost of the energy used by the CPU would be greater than the reward - so you would lose money. CPUs lose profitability when outcompeted by GPUs - Graphics Processing Units. Graphics processors take longer to complete a hash, but can do thousands of hashes simultaneously. And then GPUs were outcompeted by FPGAs. FPGAs are Field Programmable Gate Arrays - microchips containing sets of logic gates connected to switches - so that they can be arranged to act as any digital circuit (within the limits of the FPGA). They can be configured to create hashing circuits which are much faster than GPUs and use less energy. But afterward, ASIC chips - Application Specific Integrated Circuits. These are microchips that serve no other purpose than mining cryptocurrency. These are extremely expensive to purchase, but they are presently the only way to make money off of bitcoin mining. People set up giant collections of ASICs called mining farms. Below is a picture of a bitcoin mining farm in Iceland:

Bitcoin isn't the only cryptocurrency. After bitcoin became run by ASICs, Litecoin was created as an ASIC-proof alternative. Litecoin is run by ASICs, but there is a much smaller margin relative to GPUs, and prices are much lower - under $4. There is also a joke cryptocurrency called dogecoin. One cryptocurrency with a notable change is Ethereum - which adds "contracts." Contracts are programs on the ethereum blockchain which can store data and do automated and reliable transactions.

Friday, July 8, 2016

Ravi: A JIT for Lua 5.3

Recently I was looking for a JIT compiled implementation of Lua 5.3 to work with for a project. Then I found Ravi - a JIT implementation for Lua 5.3 extended with optional static typing for local variables. Ravi is available on Windows, Mac, Linux, and pretty much any other system with cmake, a C compiler, and libgccjit or LLVM. It can also be run without a JIT.

The static typing is pretty simple. Here is an example:

local a
local b: interger

Currently, variables can be statically typed as intergers, numbers, tables, interger arrays, and number arrays. Arrays are not compatable with tables because they can only be indexed by intergers. Example for declaring an array:

local c: interger[]

Arrays can be initialized similarly to tables though:

c={}

But, they are not compatable with tables:

local d: table ={}
c=d --error

The method of creating arrays mentioned before creaates dynamically sized arrays, but fixed size arrays can be declared with table.intarray and table.numarray.

JIT compilation may be either done in manual or automatic mode. In manual mode, the code must run ravi.compile on the function. As an optional second argument to ravi.compile, you may specify compiler options. In automatic mode, ravi will automatically JIT any function greater than a certain size (defaults to 150 instructions) or that has been run more than a certain number of times (defaults to 50 calls).

Ravi also has a binding for LLVM - so you can implement a JIT in Ravi. This binding can access C functions. Ravi can run normal Lua source code without a problem - but not bytecode. Ravi has a slightly different bytecode in order to accommodate additional instructions, but has a limit of 125 registers.

Ravi is by Dibyendu Majumdar and can be found here on GitHub.