REST API Specification

Connection between two systems would happen based on REST API. The API developed on one system would be accessed through another system to pull or push the data. This blog specifies a way the API is to be developed.

Request format

API would be called as a standard HTTP request. Below are the examples of GET, POST and DELETE requests that can be made to an API.


GET /api/v1/entity/parameter

POST /api/v1/entity

{
    "param1": "value1",
    "param2": "value2",
    // ...
}

DELETE /api/v1/entity/parameter


HTTP Basic Authentication can be implemented with username and password Base64 encoded and inserted in the header of API requests. These encoded credentials would be decoded and verified for the authenticity of the request made.

All API Requests can be logged with the URL and the request json data to a log file, as per “Common Log Format”
IP DATETIME HTTP_METHOD URL REQUEST_JSON_DATA

Response Format

Variable names are snake_cased

Successful request:

{
    "status": "success",
    "data": {
        /* Application-specific data would go here. */
    },
    "messages": [{}] /* Or optional success message */
    "links" : [
        {
            "href": "http://example.org/resource-path"
        }
    ]
}

Failed request:

{
    "status": "error",
    "data": null, /* or optional error payload */
    "messages": [{"Error xyz has occurred"}]
}

Below are the HTTP codes sent back in response for the HTTP methods used.

GET
– 200 Ok

POST
– 201 Created

DELETE
– 204 No Content

Errors
– 400 Bad Request
– 401 Unauthorized
– 403 Forbidden
– 404 Not Found
– 405 Method not allowed
– 422 Unprocessable Entity
– 500 Internal server error

[Tutorial] cPanel Push (Automatic) Deployment of PHP application from private GitHub repository

cPanel is (still) a popular server management software preferred by many IT managers. Web-based access makes it easy to manage and modify the server from any where. cPanel is often an integral part of WHM (Web Hosting Manager) which can control multiple cPanels and automate server management tasks easily. In the moden days, with the advent of DevOps process, we can automate the deployment of PHP application directly into cPanel using the popular code versioning systems such as Github or Bitbucket.

In this tutorial, we will implement Automatic Push deployments of PHP Application in cPanel from private Github repository. We will look at pulling code from a private repository into a selected path on your cPanel enabled server.

Step 1: Create a private repository on Github

Create a private repository as mentioned in this link – https://help.github.com/en/articles/create-a-repo

Add some code into this repository.

Step 2: Manage SSH keys between cPanel and Github

[Ref: https://documentation.cpanel.net/display/CKB/Guide+to+Git+-+Deployment ]

  • Go to cPanel > Advanced > Terminal and generate a key with this command. Important: DO NOT GIVE ANY PASSPHRASE. Leave it empty.
            ssh-keygen -t rsa -b 4096 -C "username@domain"
  • Copy the public key generated using this command
            cat ~/.ssh/id_rsa.pub
  • Leave the terminal window open, and go to your Git respository in another browser tab
  • Go to repository Settings > Deploy Keys and click on “Add deploy key” button
  • Paste the copied key in the text box and click on “Add Key” button
  • Go back to your cPanel terminal window and give this command to confirm the access. If the key is working, you will get to see a “Hi” message.
           ssh -T [email protected]

On your local system, generate a set of SSH keys to be imported into cPanel. Follow the same procedure given above to generate public and private keys. REMEMBER TO NOT GIVE ANY PASSPHRASE during the key generation.

  • Go to cPanel > Security SSH Access
  • Click on “Manage SSH Keys” button and click on “Import Key” button
  • Give a different name (other than id_rsa) and enter the private key and public key content from your local system files
  • Go to cPanel > Security SSH Access  and click on “Manage” button against your imported key
  • Click on “Authorize” button

Note: If you don’t add your local key in cPanel, you have to manually pull the code changes each time, because the repository is residing outside cPanel. To skip that process, this step is required.

Till this point, you have configured cPanel to access Github. Now we create a cPanel counterpart to link Github repository

Step 3: Creating repo in cPanel

  • Go to cPanel > Files > Git Version Control
  • Click on “Create” button
  • Enable “Clone Repository” slider and give the Github repository url in the “Clone Url” textbox. This URL would be the SSH URL of your Git repository. E.g. [email protected]:lightracers/ourprivaterepo.git
  • Enter the required path in “Repository path”
  • Give a proper name in “Repository Name”
  • Click on “Create” button

You will be shown a screen with a “Clone Url” which has your cPanel user name. Copy this URL. You would need use this in your local system.

Step 4: Updating Git references

Some of the online references will tell you that a Webhooks are automatically configured in cPanel. Automatic webhooks would work only if repository is with cPanel. It would not work in our case, because the actual repository is not with cPanel but with Github. cPanel has just cloned the repo. So we would need to update the cPanel references in your local clone.

When you modify code on your local system and “git push” it, it would go into just Github. By adding an extra reference as a pushUrl, updated code would also go to your given url.

Give a command similar to this, in local terminal inside your code repository.

git remote set-url --add --push origin ssh://username@mycpanelhost:2232/home/username/<path>

This command will add the cPanel URL as a pushUrl under [remote “origin”] section in your git config (.git/config).

Step 5: Push some code

Lets try to push some code now. Go ahead and make some modifications in your code and give these commads. You should see output from Github as well as from cPanel.

git add .
git commit -m "Push to cPanel"
git push

Go to cPanel > File Manager and open the “Repository path” you have specified in Step 3. You should be able to see the updated code automatically showing up over there.

If yes, congrats you can now work in a much simpler way. If something goes wrong, try to understand the error and see if you have missed any of the above connecting chains.

Let us know if something doesn’t work for you in the comments below. We will try to help you.

Monsoon Framework – A Lightweight, Secure, Rapid MVC PHP Framework

Monsoon Framework (monsoonphp.com) is a lightweight, secure and fast PHP framework designed for enterprise-level rapid application development (RAD) needs. It contains a folder structure that serves as placeholder to insert PHP code for your web application.

The framework is useful in creating a simple, fast and secure application quickly. It gives you an advantage to maintain Application code, API code as well as CLI based code in a single code repository. You can bring in your own composer libraries into this composer-ready framework.

Getting started is very easy with just 2 commands.

composer create-project monsoon/framework <my_project_name>
php -S localhost:8080 -t public/

Monsoon framework includes these conventions

  • PSR-1, PSR-2 and PSR-4
  • Model-View-Controller pattern
  • PDO (MySQL)
  • Composer
  • Docker
  • PHPUnit
  • PHPCS
  • PHPMD

The framework carries a MIT licence, which gives you a flexibility to use it in commercial projects. This is also an opensource framework intiated by Lightracers, giving more flexibility for developers to contribute.

Visit monsoonphp.com to know more about this new framework.

Cyber Security Awareness Session for Executives and Non-IT professionals Slideshow

Cyber Security Awareness Session conducted by Lightracers Consulting, for Management and non-IT employees. In this learning presentation, we will look at – What is Cyber Crime, Types of Cyber crime, What is Cyber Security, Types of Threats, Social Engineering techniques, Identifying legitimate and secure websites, Protection measures, Cyber Law in India followed by a small quiz.

Tuning sysctl.conf file on Ubuntu

sysctl is used to modify kernel parameters at runtime. The parameters available are those listed under /proc/sys/. Procfs is required for sysctl support in Linux. You can use sysctl to both read and write sysctl data.

/etc/sysctl.conf is the typical file, in which you can make the below modifications.

# Controls IP packet forwarding
net.ipv4.ip_forward = 0

# Ignore all ICMP ECHO and TIMESTAMP requests sent to it via broadcast/multicast
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_echo_ignore_all = 1

# Prevent against the common 'syn flood attack'
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_syn_retries = 3
net.ipv4.tcp_synack_retries = 3
net.ipv4.tcp_max_syn_backlog = 5120

net.ipv4.netfilter.ip_conntrack_max = 196608
net.ipv4.netfilter.ip_conntrack_tcp_timeout_syn_recv=45

# Controls source route verification
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.rp_filter = 1

# Accept Redirects? No, this is not router
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0

To load settings, enter:
$ sudo sysctl -p

Nginx webserver configuration

Nginx web server comes with the default website. But there will be business cases where you have to host more than one website or sub domain on your Nginx web server. In many cases, you might want to configure nginx as reverse proxy for multiple website that are hosted on your upstream server, such as Apache. This article will guide you with common configurations that tune your nginx server’s performance and offer first line of security. This article assumes that you have nginx installed on Ubuntu 16.04 LTS.

nginx.conf

Modify your nginx.conf’s http { } block with the attributes below.

user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
        worker_connections 10000;
        multi_accept on;
}
http {

    # Basic
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    types_hash_max_size 2048; 
    
    # worker connections
    worker_processes 1;
    worker_connections 1024;

    # keepalive
    keepalive_requests 500
    keepalive_timeout 65;
    
    # buffers
    client_body_buffer_size 100K;
    client_header_buffer_size 1k;
    client_max_body_size 25m;
    large_client_header_buffers 4 16k;

    #fastcgi
        fastcgi_buffers 8 16k;
        fastcgi_buffer_size 32k;
        fastcgi_connect_timeout 300;
        fastcgi_send_timeout 300;
        fastcgi_read_timeout 300;

    # timeouts
    client_body_timeout 10;
    client_header_timeout 10;
    send_timeout 10;
    
    server_names_hash_bucket_size 64;
    # server_name_in_redirect off;
     
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    
    # Logging
    access_log /var/www/nginx_logs/access.log; # or off
    # access_log off;
    error_log /var/www/nginx_logs/error.log;

    # purge cache
    map $request_method $purge_method {
        PURGE 1;
        default 0;
        }
    
    # disable bots
    if ($http_user_agent ~* LWP::Simple|BBBike|wget) {
        return 403; 
    }
    
    # restrict header types
    add_header Allow "GET, POST, HEAD" always;
    if ($request_method !~ ^(GET|HEAD|POST)$ )
    {
        return 444;
    }

    # security headers
    server_tokens off;
    # add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Content-Security-Policy "default-src 'self';";
        add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload';
    
    # Limit requests
    limit_conn_zone $binary_remote_addr zone=global_limit_conn_zone:10m;
    limit_req_zone $binary_remote_addr zone=global_limit_req_zone:10m rate=50r/s;

    # proxy cache
    proxy_cache_path /tmp/nginx levels=1:2 keys_zone=global_cache_zone:20m max_size=500m inactive=60m use_temp_path=off purger=on;
    proxy_cache_key "$scheme$request_method$host$proxy_host$request_uri";

    # SSL Settings
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
        ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:50m;
    ssl_session_timeout 10m;
      
    # gzip
    gzip             on;
    gzip_disable "msie6";
    gzip_comp_level  6;
    gzip_min_length  1000;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_vary on;
    gzip_proxied     expired no-cache no-store private auth;
    gzip_types        text/plain application/x-javascript text/xml text/css application/xml application/json application/javascript application/xml+rss text/javascript;

    # Virtual Hosts
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*.conf;

    # ..
}

Virtual Hosts

You can create individual configuration files for individual websites/subdomain sites in /etc/nginx/sites-available/.

$ sudo nano /etc/nginx/sites-available/www.example.com

Your site configuration file will typically have only server { } block. Below is the typical configuration that you can use. The configuration blocks have comments to make you understand what they mean.

server {
    listen 80;

    root /var/www/example.com/www.example.com;
    index index.php index.html index.htm;
    server_name example.com www.example.com;

    location / {
        # try_files $uri $uri/ /index.php;

        # ddos protection
        limit_req zone=global_limit_req_zone burst=20 nodelay;
        limit_req_log_level warn;
        limit_req_status 444;
        limit_conn conn_limit_per_ip 10;

        # deny IPs
        # deny 123.123.123.0/28;

        # proxy cache
        add_header X-Proxy-Cache $upstream_cache_status;
        proxy_cache global_cache_zone;
        proxy_cache_min_uses 5;
        proxy_cache_bypass  $http_cache_control;
        proxy_cache_bypass $cookie_nocache $arg_nocache$arg_comment;
        proxy_cache_methods GET HEAD POST;
        proxy_cache_valid 200 302 10m;
        proxy_cache_valid 404      1m;
        proxy_cache_valid any 5m;
        proxy_no_cache $http_pragma $http_authorization;
        proxy_cache_purge $purge_method;
      
        # reverse proxy
        include proxy_params;
        proxy_pass http://127.0.0.1:8080;
        
    }

    location ~ \.php$ {
        # include snippets/fastcgi-php.conf;
            # fastcgi_pass unix:/run/php/php7.4-fpm.sock;
    }

    location ~ /\.ht {
        deny all;
    }
    
    # security headers
    server_tokens off;
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Content-Security-Policy "default-src 'self';";
    
    # enables server-side protection from BEAST attacks
    ssl_prefer_server_ciphers on;
    ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4:@STRENGTH";
    
    # gzip responses
    gzip on;
    gzip_disable "msie6";
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
    gzip_min_length 50000;
    gzip_proxied no-cache no-store private expired auth;

    # Expire rules for static content

    # cache.appcache, your document html and data
    location ~* \.(?:manifest|appcache|html?)$ {
      expires -1;
      # access_log logs/static.log; # I don't usually include a static log
    }

    # Feed
    location ~* \.(?:rss|atom)$ {
      expires 1h;
      add_header Cache-Control "public";
    }

    # Media: images, icons, video, audio, HTC
    location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc|otf|ttf|eot|woff)$ {
        expires 1M;
        access_log off;
        tcp_nodelay off;
        add_header Vary Accept-Encoding;
        add_header Cache-Control "public";
      
        ## Set the OS file cache.
        open_file_cache max=3000 inactive=120s;
        open_file_cache_valid 45s;
        open_file_cache_min_uses 2;
        open_file_cache_errors off;
    }

    # CSS and Javascript
    location ~* \.(?:css|js)$ {
        expires 1w;
        access_log off;
        add_header Cache-Control "public";
    }
}

Once the virtual host file is added, link it to sites-available and restart the nginx server

$ sudo ln -s /etc/nginx/sites-available/www.example.com /etc/nginx/sites-enabled/www.example.com
$ sudo service nginx restart

Setup ProFTPD on AWS Ubuntu Server

ProFTPd is a popular FTP server that can be configured to use the SFTP protocol, a secure FTP alternative, instead of FTP. This article will show you how to configure ProFTPd to use this protocol to avoid the insecurity of FTP.

We will show you how to configure this on an Ubuntu 16.04, but most distributions should operate in a similar way.

Installation

The ProFTPd software is in Ubuntu’s default repositories. We can install it by typing:

$ sudo apt update
$ sudo apt install proftpd

ProFTPD can be run either as a service from inetd, or as a standalone server. Each choice has its own benefits. With only a few FTP connections per day, it is probably better to run ProFTPD from inetd inorder to save resources. On the other hand, with higher traffic, ProFTPD should run as a standalone server to avoid spawning a new process for each incoming connection. Choose “stand alone” when prompted during installation.

Configurations

After the installation is done, you have to configure the server. The configurations are present in proftpd.conf

$ sudo nano /etc/proftpd/proftpd.conf

Change the following attributes to the values given below.

  • UseIPv6 off
  • ServerName “MyFTPDServer”
  • DefaultRoot /var/www/
  • Port 990
  • PassivePorts 1024 1048
  • MasqueradeAddress xxx.xxx.xxx.xxx <- Your Elastic IP
  • RequireValidShell on
  • AuthOrder mod_auth_pam.c* mod_auth_unix.c

Save the file and restart the service.

$ sudo service proftp restart

Creating users

Default user of proftpd will be created automatically. But it is better to create another user to share among your developers.

Create a user and assign a password with these commands

$ sudo adduser ftpusername
$ sudo passwd ftpusername

Restrict the access of this user to /var/www/ only the access of this user to

$ sudo usermod -m -d /var/www/ ftpusername

Add the user to www-data group, so that users can update the files. If users are able to access folder, but can not make any changes, give this command.

$ sudo chown -R ftpusername:www-data /var/www/

You may use any FTP software, such as Filezilla or WinSCP, to connect

Enabling TLS in ProFTPD

To run the ProFTPD on TLS authentication mode, you have to generate a key. You can generate a key from the command below.

$ sudo openssl req -x509 -nodes -newkey rsa:2048 -keyout /etc/ssl/private/proftpdserverkey.pem -out /etc/ssl/certs/proftpdcertificate.pem -days 3650

TLS configurations are present in tls.conf file. You have to enable this in the proftpd.conf file.

  • Include /etc/proftpd/tls.conf

Open up the tls.conf to modify some configurations.up the tls.conf to modify

$ sudo nano /etc/proftpd/tls.conf

This file should contain the following configurations.

  • TLSRSACertificateFile /etc/ssl/certs/proftpdcertificate.pem
  • TLSRSACertificateKeyFile /etc/ssl/private/proftpdserverkey.pem
  • TLSEngine on
  • TLSLog /var/log/proftpd/tls.log
  • TLSProtocol SSLv3 TLSv1
  • TLSRequired off
  • TLSOptions NoCertRequest EnableDiags NoSessionReuseRequired
  • TLSVerifyClient off
  • TLSRenegotiate none

Save the file and restart the service.

$ sudo service proftp restart

AWS security group

From your AWS console, add the ports that you have configured in the Inbound rules list. You may want to restrict the IPs from which these ports are added. In this article, we have mentioned 990 and 1024-1048 ports. You can give other ports as per your choice/requirement.

Identify IPs from Apache logs during DDoS attack

DDoS attacks can be frustrating. More challenging is to find out the IPs from the lengthy apache logs who are putting load on your server.

Below is a command that can help you to identify the IPs and their request counts present in your log file.

grep ‘DD\/MMM’ access_log | awk -F’ ‘ ‘{ print $1 }’| sort | uniq -c | sort -r

Replace DD and MMM with the date you want to look up. Replace the “access_log” with your Apache access log path.

Configure XDebug on WAMP and Netbeans

Xdebug is an extension for PHP to assist with debugging and development. It contains a single step debugger to use with IDEs; it upgrades PHP’s var_dump() function; it adds stack traces for Notices, Warnings, Errors and Exceptions; it features functionality for recording every function call and variable assignment to disk; it contains a profiler; and it provides code coverage functionality for use with PHPUnit. This article contains a step by step instruction guide in configuring XDebug on your WAMP Server (http://www.wampserver.com/en/) on Windows.

  1. Before starting, make a note of the PHP version enabled, its Compiler and Architecture values from phpinfo().
  2. Go to https://xdebug.org/download.php and download the relevant .dll file based on the information collected in step 1.
  3. Place the downloaded dll file in your WAMP’s PHP folder. e.g. C:\wamp64\bin\php\php7.1.9\zend_ext\php_xdebug-2.5.5-7.1-vc14-x86_64.dll
  4. Open php.ini from the WampServer’s manager in the system tray, i.e. [W] > PHP > php.ini. Alternatively, you can find the php.ini in use in the WAMP folder also. e.g. C:\wamp64\bin\apache\apache2.4.27\bin\php.ini
  5. Add the code below to the bottom of your php.ini. (replace the path with the relevant one)
    [xdebug]
    
    zend_extension ="c:/wamp64/bin/php/php7.1.9/zend_ext/php_xdebug-2.5.5-7.1-vc14-x86_64.dll"
    
    xdebug.extended_info=on
    
    xdebug.profiler_enable = on
    
    xdebug.profiler_enable_trigger = on
    
    xdebug.profiler_output_name = cachegrind.out.%t.%p
    
    xdebug.profiler_output_dir ="c:/wamp64/tmp"
    
    xdebug.show_local_vars=0
    xdebug.remote_enable=on
    
    xdebug.remote_handler=dbgp
    
    xdebug.remote_host=localhost
    
    xdebug.remote_port=9000
    
    xdebug.remote_autostart=on
    
    xdebug.idekey="netbeans-xdebug"
  6. Change the below parameters to the given values.
    output_buffering = Off
    
    implicit_flush = On
  7. Save the php.ini file and restart the Apache service
  8. Verify that xdebug is enabled in your WAMP’s phpinfo page. Go to http://localhost/?phpinfo=1 and look for the section – xdebug.
  9. Configure your IDE to use xdebug

Configuring Netbeans

  1. Go to Tools menu > Options > PHP > Debugging and give the following options.
    1. Debugger port: 9000
    2. Session ID: netbeans-xdebug
    3. Maximum Data Length: 2048
    4. Stop at first line: checked
    5. Show debugger console: checked
  2. Click on OK to save the configuration
  3. Open your desired PHP file and place a breakpoint beside the line number of your choice
  4. Go to Debug menu and click on Debug Project or Debug File
  5. Netbeans will start listening to XDebug on the given 9000 port.

In this way, you can debug your PHP script using XDebug.