Tuesday, December 1, 2020

Asterisk ARI Introduction

 To enable:

Asterisk HTTP server is used to access ARI, WS, AMI. If you need WebSocket: The built-in Asterisk HTTP server is used to provide the WebSocket support. The res_http_websocket must also be built and loaded by Asterisk. For most individuals this is done by default.
You can’t view WebSockets in a standard browser. That's how the spec is written. If you view it in a standard browser the server will tell the protocol it needs to upgrade. This is to keep it in line with the HTTP spec. It doesn’t mean there is an upgrade. So don't try to access ws://yourAsteriskServerIP:8088/ws from a standard browser.

OpenAPI - specification standardizing describing of the REST API-services. This describtions can be in JSON or YAML.
Swagger – framework allowing you to describe the structure of your APIs using OpenAPI specification so that machines can read them. Also structure become more readable by humans via Swagger UI.
Don’t access ARI directly from a web page It’s very convenient to use ARI directly from a web page for development, such as using Swagger-UI, or even abusing the WebSocket echo demo to get at the ARI WebSocket. But, please, do not do this in your production applications. This would be akin to accessing your database directly from a web page. You need to hide Asterisk behind your own application server, where you can handle security, logging, multi-tenancy and other concerns that really don’t belong in a communications engine.

http.conf
[general]
enabled=yes
enablestatic=no
bindaddr=yourAsteriskServerIP
bindport=8088
servername=Asterisk 

ari.conf
[general]
enabled = yes
pretty = yes
allowed_origins = yourDeveloperHost
[testARI]
type = user
read_only = no
password = Sup3rM3ga$tr0ng
password_format = plain

asterisk -rx "module reload res_ari.so"
asterisk -rx "reload http"

It's highly recommended to use TLS and secured web socket (WSS)  server in the production environment:
openssl req -new -x509 -days 365 -nodes -out /tmp/foo.pem -keyout /tmp/foo.pem
mv /tmp/foo.pem  /var/lib/asterisk/

http.conf
tlsenable=yes
tlsbindaddr=yourAsteriskServerIP:8089
tlscertfile = /var/lib/asterisk/foo.pem
tlsprivatekey = /var/lib/asterisk/foo.pem

asterisk -rx "reload http"
asterisk -rx "http show status"

To check:

asterisk -rx "http show status"
asterisk -rx "ari show status"

From browser:
yourServerIP:8088/ari/api-docs/resources.json

To read in more user-friendly way:
  1. in ari.conf add http://ari.asterisk.org to the allowed_origins (using coma as origin separator).
  2. asterisk -rx "module reload res_ari.so" 
  3. access http://ari.asterisk.org enter yourAsteriskServerIP:8088/ari/api-docs/resources.json into the first input-placeholder, then username:password of the ARI to the second input-placeholder
  4. press "Explore"

Stasis Message Bus:

In Asterisk 12, a new core component was added to Asterisk: the Stasis Message Bus (SMB). As the name suggests, Stasis is an internal publish/subscribe message bus that lets the real-time core of Asterisk inform other modules or components – who subscribe for specific information topic – about events that occurred that they were interested in (for example: Stasis Message: Channel Hangup). SMB is used by AMI, CDR, CEL, ARI etc. Key concepts of the SMB:
  1. Message - group name of the event (ax: Channel Hangup)
  2. Publisher - source of the event (ex: Channel Core - publishes message)
  3. Subscriber - subscribes to a topic and receives messages of this topic (ex: AMI subscribed to channel event topic)
  4. Cache - Some Messages - particularly those that affect core communications primitives in Asterisk (such as channels or bridges) are stored in a special cache in Stasis. Subscribers have the option to query the cache for the last known state of those primitives.

Using Stasis diaplan application:

extensions.conf
[ARI-test]
exten => 1000,1,NoOp() 
same => n,Answer() 
same => n,Stasis(hello) 
same => n,Hangup()

 asterisk -rx "dialplan reload"

Some notes:
  1. You can't manage channel which is outside of the Stasis app
  2. You can't retrieve data from channels which are outside of the Stasis app
  3. When dialplan is in Stasis app - dialplan stays in until you exit Stasis
  4. Communication between app inside Stasis and client is done over WebSocket in asynchronous manner
  5. If nobody is connected to the app inside Stasis ("hello" app in the dialplan above) over WebSocket  - app will stop working and handover execution to the dialplan
If we have an endpoint in ARI-test context and make call to the 1000, we'll see the following in Asterisk CLI:
ERROR[39437][C-00000003]: res_stasis.c:1325 stasis_app_exec: Stasis app 'hello' not registered

The Stasis application is how a channel goes from the dialplan to a Stasis application. When a channel enters the Stasis application in the dialplan, a StasisStart event is sent to the application's associated WebSocket. So as written above - we must to have our own application which will connect to the WS serer and interact with ARI.

ARI Resources:

Resources below must be controlled by ARI in order to be reachable:
  1. asterisk - global variables,server info, configuration files etc.
  2. endpoints - list endpoint, send message etc.
  3. channels - list, create, redirect, answer, mute, ring, hold, moh, get variable, dial etc.
  4. bridges - construct sharing media among channels: list, create, add channel, remove channel etc.
  5. recordings - list, copy, stop, pause etc.
  6. sounds - list, get details etc.
  7. playbacks - playback control
  8. deviceStates - list, change etc.
  9. mailboxes - list, destroy etc.
  10. events - WbSocket events: generate etc.
  11. applications - list, subscribe etc.

Python aioari / ari:

With Python3:
pip install aioari # this is the latest version of ari.py using async swagger.py

Wiht Python2:
pip install ari

import aioari
import asyncio
client = await aioari.connect('http://yourServerIP:8088', 'username', 'password')
def stasis_start(obj, event):
    print('start')
def stasis_end(obj, event):
    print('stop')
client.on_channel_event('StasisStart', stasis_start)
client.on_channel_event('StasisEnd', stasis_end)
loop = asyncio.get_event_loop() 
loop.run_until_complete(client.run(apps="hello"))

To close loop:
loop.close()

After entering above in python shell:
 Creating Stasis app 'hello'
  == WebSocket connection from 'hostAccessingARI:65292' for protocol '' accepted using version '13'

Then we call 1000 to enter Stasis hello app:
    -- Executing [1000@ARI-test:1] NoOp("PJSIP/2222-00000017", "") in new stack
    -- Executing [1000@ARI-test:2] Answer("PJSIP/2222-00000017", "") in new stack
    -- Executing [1000@ARI-test:3] Stasis("PJSIP/2222-00000017", "hello") in new stack

In ipython shell we'll see: start

Hangup call:
stop # in ipython shell

asterisk -rx "stasis show topic ari:application/hello"
Name: ari:application/hello
Detail:
Subscribers count: 1
Forwarding topic count: 0
Duration time: 00:03:58

Ctrl+C in ipython shell (don't forget to close loop):
 Deactivating Stasis app 'hello'
 Shutting down application 'hello'
  == WebSocket connection from 'hostAccessingARI:65292' forcefully closed due to fatal write error
 Destroying Stasis app hello
    -- Remove stasis-hello/h/1, registrar=res_stasis; con=stasis-hello(0x7f0dac014d70); con->root=0x7f0dac015160
    -- Remove stasis-hello/_./1, registrar=res_stasis; con=stasis-hello(0x7f0dac014d70); con->root=0x7f0dac015160

Hangup() will only be executed if we call 1000 without previously connecting to the WebSocket. Also below will be in Asterisk CLI:
ERROR[24668][C-00000019]: res_stasis.c:1325 stasis_app_exec: Stasis app 'hello' not registered

To extend functionality of ARI app, you can use this link:

Monday, November 23, 2020

Cisco DNA quick overview

SDN (Software Defined Networking) - attempts to centralize network intelligence in one network component (SDN Controller) by disassociating the forwarding process of network packets (data plane) from the routing process (control plane).
REST (Representational state transfer) is a software architectural style that defines a set of constraints to be used for creating Web services.
API (Application Programming Interface)
YANG (Yet Another Next Generation) is a data modeling language for the definition of data sent over network management protocols and it uses either XML or JSON encoding.
Cisco DNA (Digital Network Architecture) - is SDN for campus networks. DNA supports management through REST API using YANG model.
DNA Center (DNAC) is centralized network management system aimed to be simple and intuitive in order to be used for management of all network functions and optimization of network and applications. With DNA Cisco goes beyon traditional SDN and realizes Intent-Based Network.
SDA (Software Defined Access) - policies are applied to users and applications which makes management easier. SDA used for adding policies concerned with security, segmentation, access etc.
Cisco series used in SDA are:
  1. Access - Catalyst 9200, 9300, 9400
  2. Aggregation - Catalyst 9400, 9500, 9600
  3. Core - Catalyst 9500, 9600, 9800
NDP (Network Data Platform and Assurance) - analytic platform responsible for data collecting. Collects and classifies huge amount of data sent over network (application, user and equipment data). Using data provided by NDP DNA Center Assurance produces analytics and operative information about network state and also makes forecasts. 
How typical network tasks are made with DNA:
  1. Connecting network devices - device role is defined within DNAC or device can be bought with preinstalled Plug&Play agents which are needed for this particular device
  2. Network devices software versioning - DNAC saves "gold" versions of software and administrator just applies update policies needed for particular devices or segments
  3. Scale-able access policies - traditional access policies are IP or VLAN based. Big IP addresses pools add additional complexity. DNAC applies policies to the entire network - when some devices are changed - policies remain the same
  4. Campus network segmentation - DNAC realizes that using access matrix for all device categories used in the network. When new device is added to the network segmentation is automatically made after adding this device to the needed group

MySQL DB-size, tables size


Size of all tables in particular DB (change NEEDED_DB_NAME to needed):
SELECT table_name AS "Table", 
data_length+index_length AS "Size in bytes" 
FROM information_schema.TABLES 
WHERE table_schema = "NEEDED_DB_NAME" 
ORDER BY (data_length + index_length) DESC;

Size of all DB in MySQL:
SELECT table_schema AS "Database", 
ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS "Size (MB)" 
FROM information_schema.TABLES 
GROUP BY table_schema;

Count of rows of all tables in particular DB ((change NEEDED_DB_NAME to needed):
SELECT table_name AS "Table", 
table_rows AS "Rows" 
FROM information_schema.TABLES 
WHERE table_schema = "NEEDED_DB_NAME" 
ORDER BY table_rows DESC;

Table size description (depends on system block size):
  1. index_length=data_length=16384 (total size is 32768) - empty table with index
  2. index_length=0, data_length=16384 - empty table without index (only primary key can exist)
In MySQL (INNODB):
KEY=INDEX
PRIMARY KEY=special case of UNIQUE KEY (identifies that row and also data can't be NULL)

To check index, engine, index_length, data_length, create_time (change NEEDED_TABLE_NAME):
show table status like 'NEEDED_TABLE_NAME';

DB Normal Forms (primitive description)

 Normal Forms (NF) helps to resolve possible problems with insert, update and delete DB operations. 

To be in the next level NF DB must already be in all previous levels of NF (to be in 3NF DB must already be in 1NF and 2NF).

There are plenty of normal forms but in most practical situations first three forms are enough to prevent possible problems.

1NF (first normal form)

1NFexample1: You have "children" table with "child" column storing something like "Child'sNameSurname"
1NFexample2: You have "children" table with "parent" column storing something like "Mom'sNameSurname, Dad'sNameSurname"
1NFexample3: You have "children" table with "parent1_name" and "parent2_name" columns storing something like "Mom'sName" and "Dad'sName"

To be in 1NF:
  1. The relation has a Primary Key (PK), which uniquely identifies each row in the relation.
    1. As in 1NFexample1 "child" may not be unique so you need to add "row_id" as PK
  2. Every column stores Atomic Values
    1. As in 1NFexample2 non-atomic values are in "parent" column, so we need to split this into to rows, each with "parent" column containing name of one parent
    2. Also "parent" column must be separated into "parent_name" and "parent_surname" columns
  3. There are no Repeating Groups.
    1. As in 1NFexample3 "parent1_name" and "parent_name" are repeating groups, so we need to add "parent_name" column and for each parent add one row

2NF (first normal form)

2NFexample1: You have "children" table with CPK "child_name"+"zip" and also having "city" column


To be in 2NF:
  1. DB must already be in 1NF
  2. No partial dependencies (also called partial functional dependencies) are in table
    1. That is, each non-key attribute is functionally dependent on the full PK (PK for 2NF can be only multi column PK - also called composite PK. If table is in 1NF and having single-column PK, then this table is also automatically in 2NF):
      1. As in 2NFexample2 "city" is related to "zip" (part of CPK), but not related to the "child_name", so we must add new table "locations" with "location_id", "zip", "city" columns. And use "location_id instead of "zip" as part of CPK

3NF (first normal form)

3NFexample1: You have "children" table with "row_id" PK column and "city" and "zip" columns storing something like "Child'sCity" and "Child'sZip"

To be in 3NF:
  1. DB must already be in 2NF
  2. No transitive functional dependencies - non-key column depends (functionally) on another non-key column, which is (functionally) dependent on the PK
    1. As in 3NFexample1 "zip" and "city" are related to "row_id" (PK), but also depend on each other, so we must add new table "locations" with "location_id", "zip", "city" columns. After that in "children" table we'll use "location_id" instead of "city" and "zip"

Monday, August 24, 2020

Short note about MySQL INDEX, KEY


MySQL KEY = INDEX - helps to find data faster via using indexing in needed columns

PRIMARY KEY (PRI) - repetitions in this column (or group of columns) are not allowed, NULL values are not allowed

UNIQUE KEY (UNI - one column) - repetitions in this column are not allowed, NULL values are allowed

UNIQUE KEY (MUL - multiple columns) - repetitions allowed in one column bit not in both at he same time, NULL values are allowed

INDEX=KEY - repetitions allowed, NULL values allowed

FOREIGN KEY = only value existing in other table can be added to this column

Friday, July 17, 2020

Dynamic routing - quick overview (RIP, OSPF)

Three types of dynamic routing protocols:
  1. distance vector (RIP, EIGRP) - works like signpost:
    1. Distance - how far away (metrics)
    2. Vector - which direction (interface and IP address of the next hop)
  2. link-state (OSPF) - works like GPS system and have complete notion of entire network:
    1. Link - interface of the router
    2. State - description of the interface and how this interface is connected to the neighbour
  3. path-vector routing (BGP)

RIP

RIP is Routing Information Protocol.
RIP uses hop count (number of routers you have to pass to get to the destination) as metric
RIP routers copy their routing table to their directly connected neighbors every 30 seconds and neighbor updates own routing table with new routes along with interface on which to route and metric to this route. 
If interface goes down on some router with locally connected interface, then this router can receive routing table with route to this down network and will update it's own routing table with this wrong route and after that every update for that route will increase metric by 1 going to infinity. 
To prevent that issue (so called "counting to infinity") RIP uses maximum hop count of 16.
Also RIP uses split horizon setting to prevent advertising back to the router you learnt from. 
Also if interface goes down - owner router of that interface will send immediate triggered update with metric of 16 (this process called "route poisoning"). So route poisoning overrides split horizon rule.
To prevent this router (whose interface went down) from receiving this route from somebody else - neighbor router in response of received route poison will send poison reverse. So reverse poison overrides split horizon rule.
After route route poisoning and reverse poisoning done, hold-down timer starts (default is 180 seconds) - we wait for better metric for that route if time is gone - route is removed from routing tables of two neighbor routers (which sent route poison and reverse poison).

(config) # router rip
(config-router) # version 2
(config-router) # no auto-summary
(config-router) # network 10.10.10.0
# show ip route
# show ip route rip
R 10.10.10.0/24 [120/1] via 12.12.12.12, 00:00:23 GigabitEthernet0/0

Notes:
  1. version 2 - classless (172.16.1.0 and 172.16.2.0 are seen like to different networks, not like 172.16.0.0 class network)
  2. no auto-summary -bu default RIPv2 makes auto-summary of routes
  3. R - RIP protocol
  4. [120/1] - administrative distance is 120, metric is 1
  5. via 12.12.12.12 - neighbor IP address
  6. 00:00:23 - time elapsed since last update
  7.  GigabitEthernet0/0 - local outgoing interface to the learnt network

OSPF

OSPF is Open Shortest Path First (SPF is algorithm suggested by Edsger W. Dijkstra). 
OSPF uses area notion and by default we use only area 0 (also called backbone area). To move from none-backbone area (for example from area 4 to 5) we need to route packet through backbone area and naturally all non-backbone areas must be connected to the backbone area. Non-backbone areas are called regular area.
If routers are connected to the same switch and not point-to-point then DR (Designated Router) and BDR (Backup Designated Router) election is done. DR and BDR is not property of the entire router but property of the interface of the router in the distinct mutli-access segment. Interfaces of all other routers are shown as DROTHER. Election process is per multi-access segment not per area. With point-to-point link "show ospf neighbor" command just shows "FULL/-" on both routers. Router with the highest Router ID becomes DR and the next router with highest Router ID becomes BDR. We can manually assign priorities (with "ip ospf priority 200" interface command) to the routers to change election results (by default priority is 1 and Router ID is used for elections). 
OSPF operates by sending LSA (Link-State Advertisements) to DR and BDR. Then DR sends LSA to all DROTHER routers. BDR only accepts LSAs and becomes DR if current DR becomes non-operative.
All information from LSAs is analyzed and saved in LSDB (Link-State DataBase). 
Routers only have notion of the entire network in the same area.
Routers in the backbone area are called backbone routers. Routers between 2 areas are called ABR (Area Border Routers).
OSPF router connected to the network using another routing protocol called ASBR (Autonomous System Border Router).
In OSPF route summarisation is done only on ABR and ASBR.
After enabling OSPF router starts to send OSPF hello packets. If hello packet is sent and received, then two routers become neighbors. Some fields of the hello packet must match otherwise routers can't become neighbors:
  1. Hello/Dead Interval - send hello packets each "hello interval seconds" and if response is not received in "dead interval seconds" then router considered "dead"
  2. Area ID - LSA and hello-packets are sent within the same zone
  3. Authentication password - MD5 or clear text passwords can be used
  4. Stub area and flag - OSPF has different area types. Area type must be identical or routers won't become neighbors
Also below fields are also in hello packet:
  1. Router ID - unique ID of the router is the highest IP on any active interface. In order to be independent of physical interfaces states (if interface goes down - Router ID changes) it is better to use loop-back interface (have another subnet for purpose of assigning loop-back addresses from this subnet). 
  2. Neighbors - all neighbor routers of the router sending hello packet are in the hello packet
  3. Router Priority - used to choose DR and BDR
  4. DR / BDR IP - the same meaning as the field's name
After becoming neighbors routers begin to build their LSDB.
OSPF use cost as metric. Cost is reference-bandwidth / interface-bandwidth (example: if reference-bandwidth is 100Mbps and for: 100Mbps interface cost=100/100=1 , for 10Mbps cost=100/10=10). The lower the cost the better the path. If paths have the same cost their added to the LSDB and load-balancing is used.

(config) # router ospf 1
(config-router) # default-information originate always
(config-router) # network 10.10.10.0 0.0.0.255 area 0
(config-router) # network 11.11.11.0 0.0.0.255 area 1
# show ip route
# show ip ospf neighbor
# show ip protocols
# clear ip ospf process
# show ip route ospf
O 10.10.10.0/24 [110/2] via 12.12.12.12, 00:00:23 GigabitEthernet0/0

Notes:
  1. router ospf 1 - enable OSPF and specify local PID. PID can be different on each router. Also hello-packets will be sent through all alive interfaces of that router. To disable this behaviour - execute "passive-interface" command on the interface not connected to the other routers. If interface is passive and it's network is added to the OSPF process, then network of this interface is advertised in OSPF only through non-passive interfaces.
  2. default-information originate always - advertise default route into OSPF. Default route learnt from OSPF is shown as "O*E2" in the output of the "show ip route" command.
  3.  network 10.10.10.0 0.0.0.255 area 0 - OSPF uses wildcard masks (reverse subnet mask). This command saves specified network in the local LSDB of the router and makes interface part of the OSPF advertisement process
  4. network 11.11.11.0 0.0.0.255 area 1 - OSPF ABR have OSPF process with more than one areas. Route learnt from other area (to which the router is not belonging to) is shown as O IA (OSPF Inter-Area)
  5. show ip ospf neighbor - FULL state shows that routers became neighbors
  6. show ip protocols - shows interface status (passive or non-passive) and local Router ID
  7. clear ip ospf process - this command used to stop and start OSPF process in order to for example accept newly assigned local Router ID (also we can use "router-id x.y.z.w" to assign Router ID manually)
  8.  [110/2] - administrative distance is 110, cost (metric) is 2. Cost (same as with RIP) is counted as sum of costs from source router to the destination (if needed we can manually change cost of an interface with command "ip ospf cost 50" executed in the "config-if")

Monday, June 8, 2020

Asterisk "Re-transmission timeout" errors

To avoid Re-transmission timeout errors on public sip trunks:
  1. on the firewall forward udp ports 5060, 10001-20000 to the internal ip address of your pbx
  2. on the firewall turn off any sip alg or sip transformations in the firewall
  3. either disable or set firewall udp timers to 3 minutes or more
  4. make sure your pbx has a static ip address and in the freepbx sip settings set NAT to yes
  5. turn on NAT on in your firewall
  6. if you have a static public ip address use it with your sip provider instead of registration

Asterisk AMI & AstDB (initial steps + Python connect)

First time AMI setup

vi /etc/asterisk/manager.conf minimal configuration required:
[general]
enabled = yes ;AMI
webenabled = no ;AJAM
httptimeout=120
port = 5038
bindaddr = 0.0.0.0
tlsenable=no
[admin]
secret=My$ecr3t
read=all
write=all

Test over telnet:

Wait till connected:
telnet 127.0.0.1 5038

Send below commands:
Action: Login
Username: admin
Secret: My$ecr3t
Events: off

"Enter" twice to get:
Response: Success
Message: Authentication accepted

To logoff:
Action: logoff

AstDB

To view needed permissions:
CLI> manager show commands

To write into astdb:
Action: DBPut
Family: TEST
Key: WhatEverYouWant

DBDel and DBGet are working in the same manner as DBPut above.

Python to AstDB connect

import sqlite3 # it's standard library

Learn name of the table and its structure:
connector = sqlite3.connect("/var/lib/asterisk/astdb.sqlite3")
cursor = connector.cursor()
cursor.execute("select sql from sqlite_master where type = 'table'")
print(cursor.fetchall())

cursor.close()
con.close()

VMware vCD (vCloud Director) first steps


vCloud Director — platform for managing virtual infrastructure in IaaS. 
Main notions are:
  1. Virtual datacenter (VDC) — pool of resources (CPU, RAM, HDD). This is environment where you will create virtual machines (VM), containers (vApp), networks
  2. vApp – is a container and VM placed inside vApp. vApp gives ability to group VMs. This grouping can be based on VMs purpose (mail servers, accounting etc.). vApp helps to manage this groups. Also you can use vApp templates. It's helpful when you have many VMs of the same functionalities
  3. Virtual machines (VM) — in vCloud Director you can create VM from the template or install from needed OS ISO
  4. Catalogs – thees are directories where you can store templates (vApp, VM, ISO) 
  5. Org VDC Networks – this is networks of your virtual Data Center. This networks are  accessible for all vApp and VM. Network can be isolated (without Internet access) and routed (with Internet access)
  6. vApp network - this network works only inside selected vApp and by default this network will not be accessible by VMs from other vApp.
There are two types of vCD GUI - with Adobe Flash and without of using Flash. We'll use GUI without Flash and vCD version 9.7

Adding organizational VDC network

Click on the name of needed data center. In "Networking" section select "Networks", then "ADD":
  1. Select isolated or routed network:
    1. To add routed network you must have "Edge connection" - VMware Edge gateway used to connect your VDC to the external world. Besides that all settings are identical for both isolated and routed networks
  2. Specify descriptive name for that network
  3. Specify IP address of a gateway for that network in CIDR (ex.:10.10.10.1/24)
  4. Share - if want to share this network with other VDC in your organisation
  5. Add static pools if needed (this addresses will be automatically assigned to the VMs connected to that network)
  6. Add DNS to be assigned for VM's in that network (ex.: 8.8.8.8 and 8.8.4.4)
  7. Click "FINISH"
  8. If you get : "VDC does not have any network pool associated with it." error, then your couldn't add a network
If you have Edge gateway, then you can setup DNAT / SNAT / DHCP / Firewall / VPN / Load Balancer of that gateway. Some cloud providers use dedicated VM as gateway and doesn't add any Edge gateway to the VDC. 

Adding vApp and VM

In vCD addition of VM begins from vApp addition:
  1. Add vApp from template (with installed OS)
  2. Add vApp with empty VM
  3. Add empty vApp and add VM later
Click on the name of needed data center. In "Compute" section select "vApps", then "NEW VAPP":
  1. Specify name of the vApp
  2. Click "CREATE" (to add empty vApp) or "ADD VIRTUAL MACHINE"
  3. Select needed template or create custom image
  4. Go through all suggested steps
To customize VM hardware or any other allowed parameters (VM must be powered off in order to change parameters):
  1. Compute > Virtual Machines
  2. Select VM added in vApp (or setup new VM if empty vApp addedd)
  3. Click on VM name
  4. Change all needed parameters
  5. Most used VM network types:
    1. e1000 - emulated Intel 82545EM Gigabit Ethernet, supported by most OS
    2. VMXNET family - VMware Tools must be installed in order to use this type:
      1. VMXNET first version
      2. VMXNET2 - adds Jumbo Frames and other enhancements
      3. VMXNET3 - virtualized NIC 10Gb, more stable than e1000 and uses less CPU resources
  6. Click "SAVE"
To add previously added VM to needed vApp:
  1. Compute > Virtual Machines
  2. Left click on 3 dots on the left of needed VM name
  3. Move to...
  4. Select needed vApp
  5. Select storage-policy and network
  6. "Done"
To change template's default password:
  1. Compute > Virtual Machines
  2. Click on VM name
  3. Guest OS Customization
  4. Check-box below:
    1. Enable guest customization
    2. Allow local administrator password 
    3. Require Administrator to change password on first login
  5. Uncheck-box:
    1. Auto generate password
    2. Change SID
  6. Specify password at the "Specify password"
  7. "SAVE"
Connecting to VM:
  1. Compute > Virtual Machines
  2. Left click on 3 dots on the left of needed VM name
  3. If connecting after "guest customization":
    1. Power On and Force Recustomization
  4. Select "Launch VM Remote Console":
    1. In order to connect to VM, register on https://my.vmware.com/ and download VMRC (VMware Remote Console)
    2. Ctrl + Alt to escape console screen

Tuesday, May 19, 2020

DNS record types needed for MTA server



Types of needed DNS resords (as example I'll use mysubd.webredirect.org):
  • A record points mysubd.webredirect.org to a hard coded IP address
  • MX record - point mysubd.webredirect.org to a mail server. These type of records are special for just mail servers, they can co-exist with A records, and their only use is for routing mail to a different location. All mail implementations check for this record first before attempting to route an e-mail message. If a MX record does not exist for a host, an e-mail delivery would be attempted directly to the IP that the hostname resolves to.
  • PTR record - used to perform a Reverse DNS lookup (match IP address t)
  • FCrDNS (Forward-Confirmed rDNS) - if you have A record for your subdomain (mail.mysubd.webredirect.org) and also PTR record pointing to the same subdomain-name, then you can say that you have reached FCrDNS
  • SPF record - advertise which machines are allowed to send mail on behalf of my domain
  • DKIM - is an email authentication technique that allows the receiver to check that an email was indeed sent and authorized by the owner of that domain.
  • DMARC - technical specification. Mail server decides itself which mail is good or bad using DMARC record. DMARC allows instructing a destination mail server what to do with senders that fail SPF and DKIM tests. Most notably it allows instructing them to reject such senders.


  • Adding DNS records

    Check that server IP address is not is a spammers list:
    https://mxtoolbox.com/blacklists.aspx
    https://www.senderscore.org/

    If you don't have your own url registered to DNS hosting, then register on https://www.dynu.com  (below are for Linux DNS but approach is general to all flavours of DNS).

    Add subdomains and needed records:

    A record:
    1. mail.mysubd.webredirect.org IN  A yourIPaddress
    2. Check:
      1. host mail.mysubd.webredirect.org
      2. dig -t A mail.mysubd.webredirect.org +short
    MX record:
    1. mysubd.webredirect.org. IN MX 10 mail.mysubd.webredirect.org.
    2. Check:
      1. dig -t MX mysubd.webredirect.org +short
    PTR record:
    1. yourIPaddress IN PTR mail.mysubd.webredirect.org
    2. But usually this must be set up on your ISP side
    3. Check:
      1. host yourIPaddress
    SPF record:
    1. not all servers understand SPF record (it's deprecated) so it's good to use both TXT and SPF records. Below I allow sending mail only from servers in my own subdomain:
      1. mysubd.webredirect.org.  IN TXT  "v=spf1 +mx -all"
      2. mysubd.webredirect.org.  IN SPF  "v=spf1 +mx -all"
      3. Options described:
        1. v=spf1 > use SPF v1
        2. + > allow
        3. mx > all servers in mysubd.webredirect.org MX records
        4. - > deny
        5. all > all servers not listed in SPF record
      4. Check:
        1. https://mxtoolbox.com/spf.aspx
    DKIM (create keys of length 1024 - longer keys are generally create problems because of not being supported by many hosts):
    1. create a directory to hold the keys:  mkdir -p /etc/mail/dkim
    2. Generate the keypair and extract the public key out of the private key
      1. openssl genrsa -out /etc/mail/dkim/mysubd.webredirect.org.key 1024
      2. openssl rsa -in /etc/mail/dkim/mysubd.webredirect.org.key -pubout -out /etc/mail/dkim/mysubd.webredirect.org.pub
    3. Add DKIM record:
      1. 20200514._domainkey.mysubd.webredirect.org. IN TXT "v=DKIM1;k=rsa;p=addContentOfPublicKeyHere;"
      2. ; is delimiter between parameters
      3. 20200514 - selector (I used just YYYY.MM.DD of cert generation but you can use anything you want)
    4. Check:
      1. https://dkimcore.org/tools/
    DMARC record:
    1. _dmarc.mysubd.webredirect.org.   IN TXT    "v=DMARC1;p=none;pct=100;rua=mailto:postmaster@mysubd.webredirect.org;"
      1. p > what to do (none - only for reporting / quarantine - adds to spam / reject - rejects mail)
      2. pct > percentage of mail to be filtered
      3. rua > daily report mail
    2. Check:
      1. https://dmarcian.com/dmarc-inspector/

    Thursday, May 14, 2020

    Mail server on CentOS7 (Postfix, Dovecot, Rspamd without DB)

    MTA (Mail Transport Agent) - send mail over SMTP protocol - Postfix, OpenSMTPD software (post office)
    MUA (Mail User Agent) - e-mail agent - Outlook, Thunderbird etc. (user of mailbox)
    MDA (Mail Delivery Agent) - sends mails to MUA using POP3 / IMAP protocols - Dovecot software (mailbox)

    For DNS records use https://it-tuff.blogspot.com/2020/05/dns-record-types-and-meaning-types-of.html

    mail.mysubd.webredirect.org - A / MX record
    vi /etc/hostname
    mail.mysubd.webredirect.org
    hostnamectl

    yum install postfix
    yum install dovecot

    Adding user for mail management:
    groupadd -g 5000 vmail
    useradd -s /usr/sbin/nologin -u 5000 -g 5000 vmail

    Add user postfix and dovecot to group vmail:
    usermod -aG vmail postfix
    usermod -aG vmail

    Add the folder the mails will be stored in and give rights to user vmail:
    mkdir -p /var/mail/vhosts/mysubd.webredirect.org
    chown -R vmail:vmail /var/mail/vhosts
    chmod -R 775 /var/mail/vhosts

    Create dovecot log file:
    touch /var/log/dovecot
    chgrp vmail /var/log/dovecot
    chmod 660 /var/log/dovecot

    Virtual mailboxes:
    /etc/postfix/vmailbox will be used for that job
    Make hash of this file:
    postmap /etc/postfix/vmailbox

    Virtual aliases:
    vi /etc/postfix/virtual # below example redirects all mails to mysubd.webredirect.org to the catch-all@mysubd.webredirect.org
    @mysubd.webredirect.org catch-all@mysubd.webredirect.org
    postmap /etc/postfix/virtual

    Virtual domains (if more than one domain is going to be supported then add a domain per line in the below file):
    vi /etc/postfix/virtual_domains
    mysubd.webredirect.org

    SSL certificate - choose one of below - either self signed certificate or Let's Encrypt certificate.

    Self signed certificate:
    mkdir /etc/dovecot/ssl
    cd /etc/dovecot/ssl
    openssl req -new -newkey rsa:3072 -nodes -keyout mailserver.key -days 9999 -x509 -out mailserver.crt
    country name > LT
    common name > mail.mysubd.webredirect.org

    Let's Encrypt certificate:
    allow 80 port:
    iptables -R INPUT 1 -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
    install ACME (Automated Certificate Management Environment) protocol used to automate interactions between CA and users of certs:
    yum install certbot
    Generate certificate using certbot internal webservice (--standalone option) for communication with CA:
    certbot certonly --standalone -d mail.mysubd.webredirect.org
    Add default crontab entry for automatic renewal of certificates (each cert is valid for only 90 days):
    echo "0 0,12 * * * root python -c 'import random; import time; time.sleep(random.random() * 3600)' && certbot renew -q" | sudo tee -a /etc/crontab > /dev/null
    cat /etc/crontab
    Certs are added to /etc/letsencrypt/live/mail.mysubd.webredirect.org directory:
    public key is fullchain.pem (goes to smtpd_tls_cert_file)
    private key is privkey.pem (goes to smtpd_tls_key_file)

    /etc/postfix/main.cf
    smtpd_banner = $myhostname ESMTP
    biff = no
    append_dot_mydomain = no
    recipient_delimiter = +
    readme_directory = no
    #CHANGETHIS
    myhostname = mail.mysubd.webredirect.org
    #CHANGETHIS
    mydomain = mysubd.webredirect.org
    myorigin = $mydomain
    inet_interfaces = all
    # add additional domains to the list below if needed
    mydestination = localhost, $myhostname
    mynetworks = 127.0.0.0/8
    ##VIRTUAL DOMAIN##
    virtual_mailbox_domains = /etc/postfix/virtual_domains
    virtual_mailbox_base = /var/mail/vhosts
    virtual_mailbox_maps = hash:/etc/postfix/vmailbox
    virtual_alias_maps = hash:/etc/postfix/virtual
    virtual_minimum_uid = 100
    virtual_uid_maps = static:5000
    virtual_gid_maps = static:5000
    virtual_transport = virtual
    dovecot_destination_recipient_limit = 1
    mailbox_size_limit = 0
    ##SASL##
    smtpd_sasl_auth_enable = yes
    smtpd_sasl_type = dovecot
    smtpd_sasl_path = private/auth
    smtpd_sasl_security_options = noanonymous
    smtpd_sasl_local_domain = $mydomain
    broken_sasl_auth_clients = yes
    ##TLS##
    smtpd_use_tls=yes
    smtpd_tls_security_level = may
    smtpd_tls_auth_only = no
    smtpd_tls_cert_file=/etc/dovecot/ssl/mailserver.crt
    smtpd_tls_key_file=/etc/dovecot/ssl/mailserver.key
    smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
    smtpd_tls_received_header = yes
    tls_random_source = dev:/dev/urandom
    smtpd_tls_security_level = may
    smtp_tls_security_level = may
    ##restrictions##
    smtpd_helo_required=yes
    strict_rfc821_envelopes = yes
    disable_vrfy_command = yes
    smtpd_delay_reject = yes
    ##limit rate##
    anvil_rate_time_unit = 60s
    smtpd_client_connection_rate_limit = 5
    smtpd_client_connection_count_limit = 5
    smtpd_error_sleep_time = 5s
    smtpd_soft_error_limit = 2
    smtpd_hard_error_limit = 3
    ##################
    smtpd_helo_restrictions= reject_non_fqdn_hostname,
      reject_invalid_helo_hostname,
      reject_unknown_helo_hostname
    smtpd_client_restrictions = permit_mynetworks,
      permit_sasl_authenticated,
      reject_unknown_client_hostname,
      reject_unauth_pipelining,
      reject_rbl_client zen.spamhaus.org
    smtpd_sender_restrictions = reject_non_fqdn_sender,
      reject_unknown_sender_domain
    smtpd_recipient_restrictions = permit_mynetworks,
      permit_sasl_authenticated,
      reject_invalid_hostname,
      reject_non_fqdn_hostname,
      reject_non_fqdn_sender,
      reject_non_fqdn_recipient,
      reject_unauth_destination,
      reject_unauth_pipelining,
      reject_rbl_client zen.spamhaus.org,
      reject_rbl_client cbl.abuseat.org,
      reject_rbl_client dul.dnsbl.sorbs.net
    smtpd_recipient_limit = 250
    broken_sasl_auth_clients = yes
    #message_size_limit = 120480000
    ##remove IP header##
    # requires postfix-pcre (apt-get install postfix-pcre)
    #header_checks has the following content:
    #/^\s*(Received: from)[^\n]*(.*)/ REPLACE $1 [127.0.0.1] (localhost [127.0.0.1])$2
    #
    #smtp_header_checks = pcre:/etc/postfix/header_checks

    /etc/dovecot/dovecot.conf
    auth_mechanisms = plain login
    disable_plaintext_auth = no
    log_path = /var/log/dovecot
    mail_location = maildir:/var/mail/vhosts/%d/%n
    passdb {
      args = /var/mail/vhosts/%d/shadow
      driver = passwd-file
    }
    protocols = imap pop3
    service auth {
      unix_listener /var/spool/postfix/private/auth {
        group = vmail
        mode = 0660
        user = postfix
      }
      unix_listener auth-master {
        group = vmail
        mode = 0600
        user = vmail
      }
    }
    ssl_cert = </etc/dovecot/ssl/mailserver.crt
    ssl_key = </etc/dovecot/ssl/mailserver.key
    userdb {
      args = /var/mail/vhosts/%d/passwd
      driver = passwd-file
    }
    protocol lda {
      auth_socket_path = /var/run/dovecot/auth-master
      #CHANGETHIS
      hostname = mail.mysubd.webredirect.org
      mail_plugin_dir = /usr/libexec/dovecot
      mail_plugins = sieve
      #CHANGETHIS
      postmaster_address = postmaster@mysubd.webredirect.org
    }

    /etc/postfix/master.cf
    dovecot   unix  -       n       n       -       -       pipe
      flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${recipient}

    Script to add users:
    vi add_mail.sh
    #!/bin/bash
    USAGE="Usage: $0 EMAIL PASSWORD [BASEDIR]";
    #
    if [ ! -n "$2" ]
    then
      echo $USAGE;
      exit 1;
    fi
    #
    USERNAME=$(echo "$1" | cut -f1 -d@);
    DOMAIN=$(echo "$1" | cut -f2 -d@);
    ADDRESS=$1;
    PASSWD=$2;
    #
    if [ -n "$3" ]
    then
      if [ ! -d "$3" ]
      then
        echo $USAGE;
        echo "BASEDIR must be a valid directory!";
        echo "I would have tried, $(postconf | grep ^virtual_mailbox_base | cut -f3 -d' ')";
        exit 2;
      else
        BASEDIR="$3";
      fi
    else
      BASEDIR="$(postconf | grep ^virtual_mailbox_base | cut -f3 -d' ')";
    fi
    #
    if [ -f /etc/postfix/vmailbox ]
    then
    #
      echo "Adding Postfix user configuration..."
      echo $ADDRESS $DOMAIN/$USERNAME/ >> /etc/postfix/vmailbox
      postmap /etc/postfix/vmailbox
    #
      if [ $? -eq 0 ]
      then
        echo "Adding Dovecot user configuration..."
        echo $ADDRESS::5000:5000::$BASEDIR/$DOMAIN/$ADDRESS>> $BASEDIR/$DOMAIN/passwd
        echo $ADDRESS":"$(doveadm pw -p $PASSWD) >> $BASEDIR/$DOMAIN/shadow
        chown vmail:vmail $BASEDIR/$DOMAIN/passwd && chmod 775 $BASEDIR/$DOMAIN/passwd
        chown vmail:vmail $BASEDIR/$DOMAIN/shadow && chmod 775 $BASEDIR/$DOMAIN/shadow
        systemctl restart postfix
      fi
    #
    fi

    Add previously configured postmaster mail user

    Add a new mail user:
    ./add_mail.sh user@mysubd.webredirect.org Z123456z

    systemctl enable postfix
    systemctl start postfix
    systemctl enable dovecot
    systemctl start dovecot
    systemctl status dovecot
    systemctl status postfix


    Check that postfix setting made properly:
    postfix check

    Check mail queue:
    mailq

    Force mails from queue to be sent:
    postfix flush

    To check non-default settings:
    postconf -n
    dovecot -n

    iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 993 -j ACCEPT
    iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 25 -j ACCEPT

    To check all available settings of Postfix (you can use grep to filter output):
    postconf

    yum install mailx

    echo "This is message body" | mailx -s "This is Subject" -r "user<user@mysubd.webredirect.org>"  -a "attachment_file_name" somebody@gmail.com

    Also if you just want to send mail once then postfix configuration is too simple (uncomment or add below lines in /etc/postfix/main.cf and then systemctl restart postfix):
    inet_interfaces = all
    inet_protocols = all
    mynetworks=127.0.0./8

    To check mail in console use mail (-u key shows mail for specified user):
    mail -u root
    mail -u admin

    25 —  SMTP over STARTTLS;
    80 —  HTTP for Postfixadmin and Roundcube;
    110 — POP3 через STARTTLS;
    143 —IMAP через STARTTLS;
    443 — HTTPS for Postfixadmin and Roundcube;
    465 — secured SMTP over SSL/TLS;
    587 — secured SMTP over STARTTLS;
    993 — secured IMAP over SSL/TLS;
    995 — secured POP3 over SSL/TLS.

    Mail client configuration:
    SMTP, IMAP and POP3 server: mail.mysubd.webredirect.org
    SMTP Port: 25 (or 587, or 8080. In some networks, port 25 and 587 outgoing are blocked)
    IMAP Port: 143
    POP3 Port: 110
    Security type: SSL/TLS

    username: user@mysubd.webredirect.org
    (NOT just “user”)

    You will receive a warning message for the first time you connect to each, SMTP, IMAP and POP3, because you are using a self-signed certificate.


    For SMTPS support uncomment below lines in /etc/postfix/master.cf
    smtps     inet  n       -       n       -       -       smtpd
      -o syslog_name=postfix/smtps
      -o smtpd_tls_wrappermode=yes
      -o smtpd_sasl_auth_enable=yes
      -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
      -o smtpd_sasl_type=dovecot
      -o smtpd_sasl_path=private/auth

    systemctl restart postfix

    Test:
    ss -l4n

    iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 465 -j ACCEPT

    To enable port 587 (submission) uncomment below in master.cf:
    submission inet n       -       n       -       -       smtpd

    systemctl restart postfix

    Test:
    ss -l4n

    iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 587 -j ACCEPT

    To disable port 25 comment below in master.cf:
    #smtp      inet  n       -       n       -       -       smtpd

    systemctl restart postfix

    Test:
    ss -l4n


    TO TEST MAIL SERVER SETTINGS QUALITY USE: 


    Rspamd
    yum install epel-release
    yum install luajit
    curl https://rspamd.com/rpm-stable/centos-7/rspamd.repo > /etc/yum.repos.d/rspamd.repo
    rpm --import https://rspamd.com/rpm-stable/gpg.key 
    yum update 
    yum install redis
    systemctl start redis
    systemctl status redis

    yum install rspamd

    vi /etc/postfix/main.cf
    # Milter (Mail fILTER) setup
    smtpd_milters = inet:localhost:11332
    milter_default_action = accept
    milter_protocol = 6

    systemctl restart postfix
    systemctl enable rspamd 
    systemctl start rspamd

    Check that rspamd ports are up (especially 11332 used for rspamd_proxy - postfix milter)

    To configure Rspamd:
    rspamadm configwizard
    add controller pass
    add redis 
    add redis pass

    systemctl restart redis
    systemctl status redis
    systemctl restart rspamd

    vi /var/log/rspamd/rspamd.log

    cat /etc/rspamd/local.d/redis.conf
    password = "d123456D";
    write_servers = "127.0.0.1:6379";
    read_servers = "127.0.0.1:6379";

    systemctl restart redis
    systemctl status redis
    systemctl restart rspamd

    vi /etc/rspamd/local.d/dkim_signing.conf
    allow_username_mismatch = true;
    domain {
                 mysubd.webredirect.org {
                             path = "/etc/mail/dkim/mysubd.webredirect.org.key";
                             selector = "20200514";
                             }
    }

    systemctl restart rspamd
    systemctl status rspamd


    Outlook ports 993 and 465 (both SSL) + outgoing server needs authentication

    Script to delete user:
    del_mail.sh

    #!/bin/bash
    USAGE="Usage: $0 EMAIL [BASEDIR]";
    #
    if [ ! -n "$1" ]
    then
      echo $USAGE;
      exit 1;
    fi
    #
    USERNAME=$(echo "$1" | cut -f1 -d@);
    DOMAIN=$(echo "$1" | cut -f2 -d@);
    ADDRESS=$1;
    #
    if [ -n "$2" ]
    then
      if [ ! -d "$2" ]
      then
        echo $USAGE;
        echo "BASEDIR must be a valid directory!";
        echo "I would have tried, $(postconf | grep ^virtual_mailbox_base | cut -f3 -d' ')";
        exit 2;
      else
        BASEDIR="$2";
      fi
    else
      BASEDIR="$(postconf | grep ^virtual_mailbox_base | cut -f3 -d' ')";
    fi
    #
    echo $BASEDIR
    if [ -f /etc/postfix/vmailbox ]
    then
    #
      echo "Removing Postfix user configuration..."
      sed -i "/$USERNAME/d" /etc/postfix/vmailbox
      postmap /etc/postfix/vmailbox
    #
      if [ $? -eq 0 ]
      then
        echo "Removing Dovecot user configuration..."
        sed -i "/$USERNAME/d" $BASEDIR/$DOMAIN/passwd
        sed -i "/$USERNAME/d" $BASEDIR/$DOMAIN/shadow
        systemctl restart postfix
        echo "Removing user mail directory..."
        rm -rf $BASEDIR/$DOMAIN/$USERNAME
      fi
    #
    fi

    To check rspamd work:
     rspamd_stats --log /var/log/rspamd
    Ham - is normal mail
    Spam - sent to everyone, not wanted by anyone, sent out frequently, 
    Junk - sent to specific group, can be interesting for some and irritating for the others, sent out not so frequently, 

    Wednesday, May 13, 2020

    MiktoTik first steps through console


    Commands split into hierarchical groups. Commands can be executed by going to the needed place in hierarchy (for example "ip" , then "route", then "print") or directly (just type "ip route print").
    Prompt changes to show you current location inside hierarchy.
    .. and / can be used to execute commands from other levels.

    print command is used to show item names along with item numbers (interface print). Items are interfaces, ports etc. Item numbers are assigned on a per session basis, they will remain the same until you quit the console or until the next print command is executed.

    set command is used to change properties of items using item number or name. Also one set command allows using of comma separated list of item numbers (like: interface set 0,1,3 mtu=1400)

    Tab can be used to complete commands and command abbreviations are also allowed.

    Commands common to nearly all levels of menu are:
    1. print / set  / find / get / export / enable / disable / comment
    2. remove - removes item from the list
    3. add - same as set but adds new item with the specified number
    4. edit - associated with set command and used to edit values and properties containing large amount of text
    5. move - changes the order of items in list
    The console has a built-in help, which can be accessed by typing ?. Help topic shown is about item on the left of ? sign.

    You not need to save config. Config saved automatically when you click OK in winbox or press enter in terminal.

    MikroTik has Winbox utility for administering but because of many reports of hacker attacks it is safer to use setup over SSH console - if using default firewall rules. Or if want to use Winbox - change default Winbox port and remove default user (before that add other user with admin privileges) and also allow Winbox access only from trusted IP addresses.

    To enable or disable system port of MikroTIk:
    > ip service
    ip service> print
    ip service> set 0,2,5 disable=yes #disables
    ip service> set 3 disable=no #enables

    To view firewall rules:
    /ip firewall> filter print

    Add address to the needed address-list:
    /ip firewall address-list> add list=Needed_IP_list address=8.8.8.8

    Remove IP from the list:
    /ip firewall address-list>  remove 20

    Print IP addresses in a group:
    /ip firewall address-list>  print where list=Needed_IP_list





    Wednesday, May 6, 2020

    OpenVPN, Easy-RSA: cert, cert pass, user-pass (PAM)

    Overview and initial setup


    Security and encription in OpenVPN is done by OpenSSL library and TCP protocol TLS (Transport Layer Security).
    OpenVPN can use symmetric (one key for all users) and asymmetric (each user has it's own key).
    When asymmetric cryptography is used each user has private and public key.
    Public key is used for encryption and private for decryption. Private key must stay on host where it was created and only public keys must be transferred.
    Certification authority (CA) - used to verify identity of keys.
    Сertificate Revocation List (CRL) - file is used to store revoked certificates.

    sudo yum update -y
    sudo yum install epel-release -y
    sudo yum install -y openvpn wget
    wget -O /tmp/easyrsa https://github.com/OpenVPN/easy-rsa-old/archive/2.3.3.tar.gz
    tar xfz /tmp/easyrsa
    sudo mkdir /etc/openvpn/easy-rsa
    sudo cp -rf easy-rsa-old-2.3.3/easy-rsa/2.0/* /etc/openvpn/easy-rsa
    ll /etc/openvpn/easy-rsa/

    Use user other than root (ex. admin):
    sudo chown admin /etc/openvpn/easy-rsa/

    Copy sample config files (openvpn server.conf and openssl.conf) to the OpenVPN directories:
    sudo cp /usr/share/doc/openvpn-2.4.8/sample/sample-config-files/server.conf /etc/openvpn
    cp /etc/openvpn/easy-rsa/openssl-1.0.0.cnf  /etc/openvpn/easy-rsa/openssl.cnf


    Setup vars template


    cd /etc/openvpn/easy-rsa

    Change  /etc/openvpn/easy-rsa/vars file according to below (but don't delete other setting in that file), this file will be used as template when generating certificates:
    export DH_KEY_SIZE=2048
    export KEY_SIZE=4096
    export CA_EXPIRE=3650
    export KEY_EXPIRE=3650
    # Enter the two-letter abbreviation of the country of your residence
    export KEY_COUNTRY="US"
    # This should be the abbreviation of the state of your residence
    export KEY_PROVINCE="CA"
    # Enter the name of the city you live in.
    export KEY_CITY="SanFrancisco"
    # Enter the name of your organization or company
    export KEY_ORG="Fort-Funston"
    # Enter the email address that you want to be connected to the security certificate (more than one mail is allowed)
    export KEY_EMAIL="me@myhost.mydomain"
    export KEY_EMAIL=mail@host.domain
    # Enter the domain, subdomain that resolves to your server or an IP address of your server
    # For the purpose of OpenVPN server common name can be really anything
    export KEY_CN="www.xxx.yyy.zzz"
    # You should enter server here. If you enter something else, you would also have to update the configuration files that reference server.key and server.crt
    export KEY_NAME="server"
    # Enter the name of the “Organizational Unit” to which you belong, typically either the name of your department or team
    export KEY_OU=changeme

    Verify file contents:
    sudo grep -E "(^[a-z]|^[0-9])" /etc/openvpn/easy-rsa/vars

    Generating server keys and certs


    All below are done only once, when server is setup first time

    Add directory for key-cert storage:
    mkdir /etc/openvpn/easy-rsa/keys

    Use vars template:
    source ./vars

    Remove any keys and certificates already in the folder
    ./clean-all

    Generate CA. Some questions will appear and you can hit Enter for all because of using vars template:
    ./build-ca

    Generate key-cert for OpenVPN server itself. As with CA vars template is used and you can safely "Enter" and accept defaults. You'll be prompted to enter optional password, if specified clients will enter this password each time they try to connect to OpenVPN server:
    ./build-key-server server

    Generate Diffie-Hellman which necessary if TLS/SSL is used:
    ./build-dh

    Copy generated file to the /etc/openvpn:
    cp dh2048.pem ca.crt server.crt server.key /etc/openvpn/

    Generate static key for encrypting of TLS handshake between server and client:
    sudo openvpn --genkey --secret /etc/openvpn/myvpn.tlsauth


    server.conf file


    vi /etc/openvpn/server.conf # you also can use other options in server.conf (push options are used for routing)
    port 22222 #also iptables rule will be needed iptables - I INPUT -p udp -m state --state NEW -m udp --dport 22222 -j ACCEPT
    proto udp4 #udp will work faster on slow connections
    dev tun # TUN allows routing
    ca ca.crt
    cert server.crt
    key server.key  # This file should be kept secret
    dh dh2048.pem
    topology subnet
    server 10.8.0.0 255.255.255.0
    ifconfig-pool-persist ipp.txt # file used to store DHCP infinity bindings
    keepalive 10 120
    ;tls-auth ta.key 0 #comment this out in order to use tls-crypt
    tls-crypt myvpn.tlsauth
    cipher AES-256-CBC
    user nobody
    group nobody
    persist-key
    persist-tun
    status openvpn-status.log # info about currently connected users is here
    verb 3
    explicit-exit-notify 1
    remote-cert-eku "TLS Web Client Authentication" # ensures that a server will verify that the client certificate provided is truly a client certificate, and vice versa for the client which checks that the server certificate truly aimed for a server

    Verify:
    grep -E "(^[a-z]|^[0-9])" /etc/openvpn/server.conf

    Start and verify OpenVPN server:
    sudo systemctl -f enable openvpn@server.service
    sudo systemctl start openvpn@server.service
    sudo systemctl status openvpn@server.service

    Generating client keys and certs


    cd /etc/openvpn/easy-rsa/keys
    source ./vars
    ./build-key name.surname # CN must be equal username
    ls -1 name.surname*
    name.surname.crt
    name.surname.csr
    name.surname.key

    Also other types of client cert are, for example build-key-pass will generate cert with pass. Client will be asked for that pass every time trying to connect to the OpenVPN server.

    client side configuration file


    We'll use one file approach - name.surname.ovpn:
    client
    tls-client
    remote-cert-eku "TLS Web Server Authentication"
    proto udp
    remote www.xxx.yyy.zzz 22222 udp
    dev tun
    topology subnet
    pull
    user nobody
    group nobody
    persist-tun
    persist-key
    cipher AES-256-CBC
    keysize 256
    tun-mtu 1500
    auth-nocache
    <ca>
    ca.crt content goes here
    </ca>
    <cert>
    name.surname.crt content goes here
    </cert> 
    <key> 
    name.surname.key content goes here
    </key>
    <tls-crypt>
    /etc/openvpn/myvpn.tlsauth content goes here
    </tls-crypt>


    Using OpenVPN server as gateway


    Enable packet forwarding through OpenVPN server (here only ipv4 forwarding is enabled):
    vi /etc/sysctl.conf
    # Controls IP packet forwarding
    net.ipv4.ip_forward = 1
    sysctl -p

    If you want to "hide" OpenVPN client addresses while accessing network behind OpenVPN server (eth0 in example is gateway NIC on OpenVPN server):
    iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
    service iptables save

    If you want to redirect all client traffic to the OpenVPN server (Internet and all other traffic):
    push "redirect-gateway def1 bypass-dhcp"
    push "dhcp-option DNS 8.8.8.8"
    push "dhcp-option DNS 8.8.4.4"

    sudo systemctl restart openvpn@server.service
    sudo systemctl status openvpn@server.service

    Revoking user certificates


    To revoke user cert:
    source ./vars
    ./revoke-full name.username

    After that crl.pem is generated inside /etc/openvpn/easy-rsa/keys/ directory and also index.txt file is changed. index.txt file contains list of all generated certificates and information concerning their validity: V - valid or R - revoked.

    If revoke cert is not working verify than name.surname.crt file is not empty, if empty, then:
    grep name.surname index.txt
    Note number of needed user (ex. 07), then:
    cp keys/07.pem keys/name.surname.crt
    source ./vars
    ./revoke-full name.surname

    After that crl.pem must be copied to /etc/openvpn every time it is changed:
    cp crl.pem /etc/openvpn

    Also crl-verify crl.pem line must be added to the server.conf

    Then restart and verify OpenVPN server (restart is needed only first time after additon of crl-verify parameter):
    systemctl restart openvpn@server
    systemctl status openvpn@server

    By revoking the original certificate, it is possible to generate a new certificate/key pair with the user’s original common name.

    Using PAM authentication


    Using PAM (Pluggable Authentication Modules) authentication (/etc/pam.d/):

    1. add user with the same name as in your CN of the client certificate. This user will be without /home directory and ability to login: 
      1. useradd -M -s /sbin/nologin name.surname
      2. passwd name.surname
    2. edit /etcp/openvpn/server.conf and add:
      1.  plugin /etc/openvpn/openvpn-plugin-auth-pam.so login
    3. copy plugin to the /etc/openvpn :
      1. cp /usr/lib64/openvpn/plugins/openvpn-plugin-auth-pam.so /etc/openvpn
    4. systemctl restart openvpn@server
    5. sudo systemctl status openvpn@server
    6. on client side add auth-user-pass to the configuration
    7. now when trying to connect to the OpenVPN server you'll be prompted for (created above)) user-password

    Thursday, April 30, 2020

    Fail2ban install and setup

    Installation

    sudo yum install fail2ban
    sudo systemctl enable fail2ban
    sudo systemctl start fail2ban
    sudo systemctl status fail2ban

    Overview

    Fail2ban log file is  /var/log/fail2ban.log

    Fail2ban analyzes log files in logpath (default paths are in /etc/fail2ban/paths-*.conf files) and finds patterns which are described in filter (filter names are file-names inside /etc/fail2ban/filter.d directory) if IP is not in ignoreip. When found pattern repeated maxretry times during findtime seconds, then one or more actions (action names are file-names are inside /etc/fail2ban/action.d) is performed and the effect of an action is continued during bantime seconds.

    Initial setup

    Configuration parts related to some port, logpath are called jails. By default all jails are disabled.

    Fail2ban main jails configuration file is /etc/fail2ban/jail.conf but this file must not be changed manually and general approach is to create custom jail files inside /etc/fail2ban/jail.d/ and naming them .conf or .local
    All .local files are parsed after .conf files in the original configuration file and files under .d directory.   Settings  in  the  file  parsed later take precedence over identical entries in previously parsed files.

    Let's setup our own defaults:
    vi /etc/fail2ban/jail.d/default.conf and add below:
    [DEFAULT]
    maxretry = 4
    findtime = 86400
    bantime = 86400 #to make permanet (forever) ban use bantime=-1
    action = iptables-allports[name="ALL"]
    #ignoreip = 127.0.0.1/8 #don't use this subnet ignore

    [DEFAULT] is the default jail name, so settings inside this jail are inherited by all other jails and if needed one can change this defaults inside other jail.

    Understanding iptables related actions:
    1) actionstart from the [Definition] section is used to perform an action
    2) from Fail2ban version 0.10.0 actionstart is performed at the first ban (iptables rule will be created only when some IP is banned)
    3) to create rule for action before actual ban, use  actionstart_on_demand=false for each specified iptables action
    4) parameters for action are between "<" and ">" brackets
    5) so for if we use iptables action:
    First review actionstart:
    actionstart = <iptables> -N f2b-<name>
                  <iptables> -A f2b-<name> -j <returntype>
                  <iptables> -I <chain> -p <protocol> --dport <port> -j f2b-<name>
    Write your action (below is an example, you can assign not all but some of the parameters and remain the rest unchanged):
    action = iptables[name="SSHD", protocol="tcp", port="22"]

    To see all Fail2ban active configuration:
    fail2ban-client -d

    Check filter work:
    fail2ban-regex /var/log/messages /etc/fail2ban/filter.d/sshd.conf

    SSH

    add new jail for ssh protocol:
    vi /etc/fail2ban/jail.d/sshd.conf

    [sshd] 
    enabled = true 
    port = ssh 
    filter = sshd 
    action = iptables[name="SSHD", protocol="tcp", port="22"]
    logpath = /var/log/secure 
    maxretry = 3

    Asterisk

    vi /etc/fail2ban/jail.d/asterisk.conf

    [asterisk]
    enabled=true
    maxretry=5
    bantime=-1


    Postfix

    vi /etc/fail2ban/jail.d/postfix-aggressive.conf

    [postfix]
    mode=aggressive
    enabled  = true
    logpath  = /var/log/maillog
    maxretry = 3

    Dovecot

    vi /etc/fail2ban/jail.d/dovecot.conf

    [dovecot]
    enabled = true
    filter = dovecot
    logpath = /var/log/dovecot
    maxretry = 3



    Unbanning and monitoring bans

    To view configured (active) jails:
    fail2ban-client status

    To view current ban statistics (filter and actions) and current bans (if any) for specified jail:
    fail2ban-client status sshd

    To unban IP (example of unbanning IP from sshd jail):
    fail2ban-client set sshd unbanip 192.168.1.1

    Also we can use iptables for viewing of rules and unbanning:
    1) View rules along with their numbers:
    iptables -L  -n --line-numbers
    2) Unban (example is for SSHD by deleting rule with IP address to unban:
    iptables -D f2b-SSHD 1