Listing posts

Displaying posts 1 - 5 of 202 in total
Setup fail2ban to protect services
mouse 531 · person cloud · link
Last update
2019-09-12
2019
09-12
«secure apps/server with fail2ban jails
ssh and ssh ddos»

Install fail2ban:

1
apt-get install fail2ban

Configure fail2ban:

Put this file in in /etc/fail2ban/jail.d/local.conf (it is a modified copy of jail.conf):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[DEFAULT]
# space separeted list of IP addresses, CIDR masks, DNS hosts
ignoreip = 127.0.0.1/8 192.168.1.1/24

# number of seconds that a host is banned
bantime  = 3600

# a host is banned if it has generated "maxretry" during the
# last "findtime" seconds
findtime = 600
maxretry = 1

[sshd]
enabled  = true
maxretry = 1

[sshd-ddos]
enabled  = true
maxretry = 1

Note: on debian 8 put it in /etc/fail2ban/jail.local with these different blocks instead:

1
2
3
4
5
6
7
8
9
10
11
12
13
[ssh]
enabled  = true
port     = ssh
filter   = sshd
logpath  = /var/log/auth.log
maxretry = 1

[ssh-ddos]
enabled  = true
port     = ssh
filter   = sshd-ddos
logpath  = /var/log/auth.log
maxretry = 1

Starting, status, unblock IPs:

1
2
3
4
5
6
7
# restart service after any config modification
systemctl restart fail2ban

# show jailing info/counters
fail2ban-client status
fail2ban-client status sshd
fail2ban-client status sshd-ddos

To unlock blocked IPs:

1
2
fail2ban-client unban IP1 IP2 IP3 ...
fail2ban-client unban --all

SSH tips

You can allow or deny access to specific users by editing /etc/ssh/sshd_config:

1
2
3
4
5
# allow ssh access only to users A and B and disallow all the others
AllowUsers user_a user_b

# deny ssh access only to users A and B and allow all the others
DenyUsers user_a user_b

in this way the SSH demon triggers a faster failure+ban for the disallowed users.


Source: debianizzati, digitalocean


~~~ * ~~~

gitconfig global file and tools
mouse 523 · person cloud · link
Last update
2019-09-11
2019
09-11
« — »
  • Setup a main config file in /etc/gitconfig or ~/.gitconfig:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
[alias]
  co = checkout
  ci = commit
  st = status
  br = branch
  df = diff --staged
  cp = cherry-pick
  bd  = branch --edit-description
  bds = !GIT_EDITOR=cat git branch --edit-description | grep -v "^#"
  pom = push origin master
  lom = pull origin master
  poa = push origin alb
  loa = pull origin alb
  lst = ls-tree --full-tree -r HEAD
  hist = log --pretty=format:\"%h %ad | %s%d [%an]\" --date=short
  histg = log --pretty=format:\"%h %ad | %s%d [%an]\" --graph --date=short
  undoci = reset --soft HEAD^
  redoci = commit -c ORIG_HEAD
  stash-unapply = !git stash show -p | git apply -R
  stash-diff = stash show -p
  ; drop all local commits and align with origin/master
  reset-om = reset --hard origin/master
  ; side-by-side diff commands (install ydiff command)
  dfs   = !git diff  --staged | ydiff -s -w 0 -t 2 --wrap
  diffs = !git diff           | ydiff -s -w 0 -t 2 --wrap

[user]
  name  = Alberto Cavalin
  email = acavalin@users.noreply.github.com

[credential "https://github.com"]
  username = acavalin

[core]
  autocrlf = input
  safecrlf = true
  editor = nano
  excludesfile = ~/.gitignore_global

[push]
  default = current

[color]
  ui = true
  • Enable adding CR/LF files
1
2
git config --global core.autocrlf false
git config --global core.safecrlf false

resulting in this ~/.gitconfig:

1
2
3
[core]
  autocrlf = false
  safecrlf = false
  • Setup the ignore list in ~/.gitignore_global:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# jEdit temporary files
*.marks
\#Untitled-*#

# Rails files (db, log, temp, cfg)
/db/*.sqlite3
/db/*.sqlite3-journal
/log/*.log
/log/*.gz
/tmp
Gemfile.lock
/config/database.yml

.DS_Store
nohup.out
  • Use a side-by-side colored diff tool

  • Enhance the terminal experience:

    1
    2
    3
    [ -f "$HOME/.git-completion.bash" ] && source "$HOME/.git-completion.bash"
    [ -f "$HOME/.git-prompt.sh" ] && source "$HOME/.git-prompt.sh"
    export PROMPT_COMMAND='__git_ps1'
    
  • Install some good interfaces for git:

1
2
apt-get install tig  # ncurses-based text-mode interface
apt-get install gitg # gtk visual repository viewer
  • Look for a file in a project:
1
grep --color=always --exclude-dir=".git" -rin term . | less -R

Source: cache username/pass via StackOverflow and GitHub; dev.to git terminal, side-by-side diff, add CR/LF files

See also: When to Use Git Reset, Git Revert & Git Checkout


~~~ * ~~~

Common bashrc settings
mouse 460 · person cloud · link
Last update
2019-09-11
2019
09-11
« — »
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
PS1="\[\033[0;36m\]\t\[\033[01;34m\][\w]\[\033[00m\]\n\[\033[01;32m\]\u@\h\[\033[00m\]\$ "
[ $EUID -eq 0 ] && PS1="\[\033[01;34m\][\w]\[\033[00m\]\n\[\033[01;31m\]\u\[\033[00m\]# "
PATH=".:$HOME/bin:/opt/bin:$PATH"
EDITOR=/bin/nano
CONCURRENCY_LEVEL=`grep processor /proc/cpuinfo|wc -l`
HISTSIZE=10000
export PS1  PATH  EDITOR CONCURRENCY_LEVEL  HISTSIZE

alias d='clear; ls -lhX --color'
alias md=mkdir
alias cls=clear
alias cd..='cd ..'
alias rm='rm -i'
alias x=exit
alias dum='du -h --max-depth=1'
alias dumm='du -h --max-depth=1|grep M'
alias df='df -h'
alias see=geeqie
alias Grep=grep
alias Less=less
alias java='java -server'
[ -f /usr/lib/mc/mc.sh ] && . /usr/lib/mc/mc.sh

~~~ * ~~~

Securely backup files to an online drive with gocryptfs
Last update
2019-09-07
2019
09-07
«encrypted online backup»

We can easily accomplish this by using rclone on top of gocryptfs, just remember to:

  • do not lose the .gocryptfs.reverse.conf volume's settings file
  • disable online storage automatic file versioning to increase security

Note: in the future we could use rclone crypt but at the moment it is not the best option available.

Backup

1
2
3
4
5
6
7
8
# 1. setup the encrypted virtual fs
gocryptfs -init -reverse plain enc
# 2. move away volume settings
fusermount -u enc
mv plain/.gocryptfs.reverse.conf plain-gcfs.conf
# 3. remount and start the backup
gocryptfs -reverse -conf plain-gcfs.conf plain enc
rclone sync enc remote:/path/to/dest

Restore

  • Direct mount via rclone mount:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 1. mount the online drive on a local folder
    rclone mount remote:/path/to/backup enc
    # 2. mount the unencrypted virtual fs
    gocryptfs -conf plain-gcfs.conf -serialize_reads enc plain
    # 3. restore the backup
    rsync -avi plain/ /path/to/restore/
    # 4. umount the virtual fs in backward order
    fusermount -u plain
    fusermount -u enc
    
  • Dump and decrypt (requires twice the space):

    1
    2
    3
    4
    5
    6
    7
    8
    # 1. temporary dump of the online drive
    rclone sync remote:/path/to/backup enc
    # 2. mount the unencrypted virtual fs
    gocryptfs -reverse -conf plain-gcfs.conf enc plain
    # 3. restore the backup
    rsync -avi plain/ /path/to/restore/
    # 4. umount the vfs
    fusermount -u plain
    

~~~ * ~~~

Setup a VPN to protect your privacy
Last update
2019-09-02
2019
09-02
«proxy.sh vpn»

Configuration

The following instructions use the wonderful proxy.sh VPN provider: they are cheap, transparent, strongly privacy oriented, and they offer many servers, proxies and scriptable web APIs!

If you want to buy an account then click the following banner:

or just start installing and configuring the software:

1
apt-get install openvpn netselect

Create the proxysh.auth text file containing your VPN credentials:

1
2
3
mkdir -p /path/to/myvpn
cd /path/to/myvpn
echo -e "myusername\nmypassword" > proxysh.auth

Setup an openvpn config updater script, say proxysh-update.sh and substitute username, password with your VPN credentials:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#!/bin/bash

OVPND=/path/to/openvpn/config

cat > $OVPND/proxysh.conf.tmp <<VPNCFG
# https://openvpn.net/index.php/open-source/documentation/manuals/65-openvpn-20x-manpage.html
client
dev   tun
proto tcp
port  443
auth            SHA512
auth-user-pass  $OVPND/proxysh.auth
cipher          AES-256-CBC
remote-cert-tls server
resolv-retry    infinite
verb            3
reneg-sec       0
route-method    exe
route-delay     2
mute            2
mute-replay-warnings
nobind
comp-lzo

# https://community.openvpn.net/openvpn/wiki/IgnoreRedirectGateway
#pull-filter     ignore redirect-gateway

# args: tun_dev tun_mtu link_mtu local_ip remote_ip [init|restart]
up-restart
script-security 2
up              $OVPND/proxysh-cmd-up.sh
#down           $OVPND/proxysh-cmd-down.sh

# ping every N seconds and restart after M without reply
keepalive       30 90

<ca>
-----BEGIN CERTIFICATE-----
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
TSMSym4Np+AmT7OX
-----END CERTIFICATE-----
</ca>

#remote-random

VPNCFG

echo -n "`date +'%F %T'`: refresh config servers... "

# get servers list with load < 80%
post_auth=`cat $OVPND/proxysh.auth | tr "\n" "#" | sed -r 's/([^#]+)#([^#]+).*/u=\1\&p=\2/'`
curl -s -X POST https://proxy.sh/api.php -d "$post_auth" | \
  sed 's/^ *//' | tr -d "\n" | sed 's/<.server>/\0\n/g' | \
  grep -Ev "Hub" | grep -Ev "load>(100|[5-9][0-9])" | \
  sed -r 's/.*ress>(.+)<.add.*load>(.+)<.server_load.*/\1/' \
  > $OVPND/proxysh.srv
# check servers length
if [ `cat $OVPND/proxysh.srv | wc -l` -eq 0 ]; then
  echo " DL ERROR!"
  exit
fi

# order servers by ping time (UDP)
sudo netselect -s 64 `cat $OVPND/proxysh.srv | tr "\n" " "` 2> /dev/null | \
  sed 's/.* /remote /' >> $OVPND/proxysh.conf.tmp

# check servers length
if [ `grep -E "remote [0-9]+" $OVPND/proxysh.conf.tmp | wc -l` -eq 0 ]; then
  echo " SORT ERROR!"
  exit
fi

# update the real config file
chmod 600 $OVPND/proxysh.conf.tmp
mv -f $OVPND/proxysh.conf.tmp $OVPND/proxysh.conf
rm -f $OVPND/proxysh.srv
echo "OK"

Create an optional proxysh-cmd-up.sh script that run after each openvpn start/restart:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash
# script args:  tun_dev  tun_mtu  link_mtu  local_ip  remote_ip  [init|restart]

# updating deluge listen_interface IP address
if [ -d $HOME/.config/deluge ]; then
  cd $HOME/.config/deluge

  sed -i -r 's/("listen_interface": ")(.*)(")/\1'$4'\3/' ./core.conf

  if pgrep deluged > /dev/null ; then
    sudo -u cloud deluge-console "pause  *"
    sudo -u cloud deluge-console "config -s listen_interface $4" ; sleep 3
    sudo -u cloud deluge-console "resume *"
  fi

  cd -
fi

exit 0

Create a script to start and keep running the openvpn daemon say run.sh:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#!/usr/bin/sudo /bin/bash

[ `whoami` != "root" ] && { echo "you must be root!" && exit 1; }

cd /path/to/myvpn || { echo "pwd not found!" && exit 2; }

# read current config for later usage
tbl=10
dev=`ip link  | paste - - | grep -iE "state up.+ether" | head -n 1 | sed -r 's/[0-9]+: ([^:]+).+/\1/'` # device name
met=`ip route | grep -E "^default via.+dev $dev.+metric" | sed -r 's/^.+metric ([0-9]+)[^0-9]*/\1/'  ` # metric
sub=`ip route | grep -E ".+\/.+dev $dev .+metric $met" | sed -r 's/^([0-9.]+\/[0-9]+).+/\1/'         ` # subnet
src=`ip route | grep -E ".+\/.+dev $dev .+metric $met" | sed -r 's/.+src ([0-9.]+) .+/\1/'           ` # source
gwy=`ip route | grep -E ".+via.+dev $dev.+metric $met" | sed -r 's/.+via ([0-9.]+) .+/\1/'           ` # gateway
# echo -e "dev: $dev\nmet: $met\nsub: $sub\nsrc: $src\ngwy: $gwy"

if [ -z "$tbl" -o -z "$dev" -o -z "$met" -o -z "$sub" -o -z "$src" -o -z "$gwy" ]; then
  echo "configuration error"
  exit
fi

flg_restart="/tmp/openvpn.restart"
flg_iproute="/tmp/openvpn.routes"

del_ext_routes_rules () {
  echo "  deleting old routes..."                                                       
  ip route del default via $gwy table $tbl dev $dev # local gateway ip
  ip route del to          $sub table $tbl dev $dev # local subnet
  ip rule  del from        $src table $tbl          # local ip
} # del_ext_routes_rules

add_ext_routes_rules () {
  echo "  adding routes..."
  ip rule  add from        $src table $tbl          # local ip
  ip route add to          $sub table $tbl dev $dev # local subnet
  ip route add default via $gwy table $tbl dev $dev # local gateway ip
} # add_ext_routes_rules

# allow ssh via on non vpn address while vpn is open
# https://forums.openvpn.net/viewtopic.php?f=15&t=7163&start=20
# https://serverfault.com/questions/659955/allowing-ssh-on-a-server-with-an-active-openvpn-client
allow_outside_connections_to_eth () {
  echo "`date +'%F %T'`: updating routes..."

  # fix random lock out by deleting previous rules/routes
  del_ext_routes_rules ; sleep 1
  del_ext_routes_rules 2> /dev/null # paranoia

  # re-add rules/routes
  add_ext_routes_rules
} # allow_outside_connections_to_eth

# another idea to check connection is up: try pinging vpn server ip (ping -c1 -w5 -q \`ip route|grep via.*eth0|sed ...\`)
# here instead we check SSH connectivity:
ensure_ssh_from_outside_via_eth () {
  tun_ip=`ip route | grep "tun.*src" | cut -f 9 -d ' '`
  cur_ip=`dig -b $src @208.67.222.222 +short myip.opendns.com`

  #[ -n "$tun_ip" -a -n "$cur_ip" ] && \
  #  { nc -w 5 -z -s $tun_ip $cur_ip 22 || allow_outside_connections_to_eth; }

  if ! [ -n "$tun_ip" -a -n "$cur_ip" ] ; then
    echo "`date +'%F %T'`: tun/eth IPs unavailable, stopping VPN..."
    quit_openvpn
    return
  fi

  if nc -w 5 -z -s $tun_ip $cur_ip 22 ; then
    rm -f $flg_iproute
  else
    if ! [ -f "$flg_routes" ]; then
      allow_outside_connections_to_eth
      touch $flg_iproute
    else
      echo "`date +'%F %T'`: no access from outside, stopping VPN..."
      quit_openvpn
      rm -f $flg_iproute
    fi
  fi
} # ensure_ssh_from_outside_via_eth

quit_openvpn () {
  # clean status
  rm -f $flg_iproute
  del_ext_routes_rules

  pkill openvpn ; sleep 2
  pgrep openvpn > /dev/null && pkill -KILL openvpn
} # quit_openvpn

canary_failed () {
  echo "`date +'%F %T'`: CANARY FAILED ($1)! stopping VPN & exiting..."
  quit_openvpn
  exit
} # canary_failed

# exit if requested
if [ "$1" = "stop" ]; then
  quit_openvpn
  exit
fi

# infinite loop run/check/restart openvpn
while : ; do
  ts=`date +'%F %T'`

  # test proxy.sh warrant canary at 3AM
  psh_canary="/tmp/proxysh-${ts:0:10}.canary"
  if [ ! -f $psh_canary -a "03" = "${ts:11:2}" ]; then
    echo "$ts: testing warrant canary..."
    rm -f /tmp/proxysh-*.canary # purge previous file
    wget -q -O - https://proxy.sh/canary | gzip -9 -c > $psh_canary
    # test messages list
    cnd='The below "warrant canary" has been generated on: ' #`date +%F`
    cn1="To this date, there has been no warrants, searches or seizures that have not been reported in our Transparency Report, and that have actually taken place. The sky is blue :)"
    cn2="No warrants, searches or seizures of any kind, other than those reported via our Transparency Report, have ever been performed on proxy.sh assets, including in the following locations:"
    # test messages presence
    zgrep "$cnd" $psh_canary # print generation date
    zgrep "$cn1" $psh_canary > /dev/null || canary_failed "cn1"
    zgrep "$cn2" $psh_canary > /dev/null || canary_failed "cn2"
  fi

  if ! pgrep openvpn > /dev/null ; then
    ./proxysh-update.sh

    echo "$ts: restarting openvpn..."
    echo "${ts:0:10}" > $flg_restart # update restart flag
    allow_outside_connections_to_eth > /dev/null 2>&1
    openvpn --config proxysh.conf --daemon
    sleep 20
  fi

  # check SSH is reachable from outside via eth0 every 10 minutes
  [ "${ts:15:1}" = "0" ] && ensure_ssh_from_outside_via_eth

  # restart daily at 1AM
  if [ "$(<$flg_restart)" != "${ts:0:10}" -a "01" = "${ts:11:2}" ]; then
    echo
    echo "$ts: daily stopping..."
    quit_openvpn
  fi

  #echo -en "$ts\r"

  sleep 15
done

the ip commands are used to keep allowing incoming traffic from the previous default gateway 192.168.1.1 to the initial ip 192.168.1.110 in order to continue accessing your host services from the outside.

Note: Rarely you may lost connectivity via your physical interface (eg: dig -b 192.168.1.110 ...) for apparently no reason... just restart the networking service and vpn:

1
sudo pkill openvpn && sudo systemctl restart networking && ./run.sh

this should not happen anymore thanks to the ensure_ssh_from_outside_via_eth function.

Extras

  • To know your public IPs while openvpn is running type:
1
2
dig                  @208.67.222.222 myip.opendns.com # get VPN server IP
dig -b 192.168.1.110 @208.67.222.222 myip.opendns.com # get ISP public IP
1
2
3
socks.proxy.sh:1080  # useable inside the vpn (no auth required)
ext-eu.proxy.sh:1080 # useable outside the vpn (same VPN credential)
ext-us.proxy.sh:1080 # useable outside the vpn (same VPN credential)
1
2
3
# Note: VPN servers must have different IPs
ip route add IP_OF_1st_VPN_SERVER dev WAN_INTERFACE     # eth0/wlan0
ip route add IP_OF_2nd_VPN_SERVER dev 1st_VPN_INTERFACE # tun0
  • In order to retain connectivity to your default interface and just create a new virtual interface tun0 for a separate use, you can override pushed routes from the server by adding these lines to the configuration file:
1
2
3
4
route   0.0.0.0 192.0.0.0 net_gateway
route  64.0.0.0 192.0.0.0 net_gateway
route 128.0.0.0 192.0.0.0 net_gateway
route 192.0.0.0 192.0.0.0 net_gateway

Run the vpn inside a network namespace

Run openvpn telling it to not configure the tunX interface:

1
2
3
4
5
openvpn --config proxysh.conf \
  --ifconfig-noexec --route-noexec \
  --up       proxysh-cmd-netns.sh \
  --route-up proxysh-cmd-netns.sh \
  --down     proxysh-cmd-netns.sh

namespace creation and network configuration are then managed by the proxysh-cmd-netns.sh script1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/bin/sh

case $script_type in
  up)
    ( ip netns list | grep -qs proxysh ) || ip netns add proxysh
    ip netns exec proxysh ip link set dev lo up
    ip link set dev "$1" up netns proxysh mtu "$2"
    ip netns exec proxysh ip addr add dev "$1" \
      "$4/${ifconfig_netmask:-30}" \
      ${ifconfig_broadcast:+broadcast "$ifconfig_broadcast"}
    if [ -n "$ifconfig_ipv6_local" ]; then
      ip netns exec proxysh ip addr add dev "$1" \
        "$ifconfig_ipv6_local"/112
    fi
    ;;
  route-up)
    ip netns exec proxysh ip route add default via "$route_vpn_gateway"
    if [ -n "$ifconfig_ipv6_remote" ]; then
      ip netns exec proxysh ip route add default via \
        "$ifconfig_ipv6_remote"
    fi
    ;;
  down)
    # do not delete the namespace: keep it in case of server disconnection
    #ip netns delete proxysh
    ;;
esac

Once the VPN is up and running you can launch programs in the proxysh network namespace as root like this:

1
ip netns exec proxysh   su username -l -c "command arguments"

or you can conveniently use this script:

1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/sudo /bin/bash

function die() {
  echo "USAGE: netns-exec namespace cmd [arguments...]"
  exit
}

([ -z "$1" ] && die) || NS_NAME="$1" ; shift # check namespace
([ -z "$1" ] && die) || NS_CMD="$1"  ; shift # check command

RUN_CMD="$NS_CMD $@"
ip netns exec $NS_NAME su $SUDO_USER -l -c "${RUN_CMD}"

Source: OpenVPN manpage, Proxy.sh raspi howto, allow SSH via eth0, up/down scripts, UFW limit traffic on eth0 & paste.bin script, Deluge vpn/proxy guide, Proxy.sh SOCKS, Deluge VPN 1 and 2, Getting started with Proxy.sh VPN, Ignore pushed routes on Superuser and OpenVPN docs

Tips: test reacable port on server with NC, get SSH server key fingerprint