Category Archives: Web Development

Renew Expired SSL Certification in Nginx Server

Each SSL Certification has its own valid date. When your server’s certification is expired, your website will be not visitable. In this case, you need to renew your expired certification. It is quite simple and easy. But Here I just write it down to record its steps.

Step1: check its valid date

openssl x509 -in domain.crt -noout -enddate

Step2: copy the new certificate files to your server

This step depends on your service, I mean which SSL service you get. For me, I get this service from Godaddy. I need to go to Godaddy to get new crt files. There are two crt files which you need to download.

And then you need to use SCP command to copy these files to your server. If you forget the target location, you just need to go to your Nginx’s conf file to check this parameter: ssl_certificate and you will know where to copy to.

Here is an example of SSL part in Nginx.

ssl on;
ssl_certificate /etc/ssl/domain.crt;
ssl_certificate_key /etc/ssl/domain.key;

Here ssl_certificate is your primary certificate; ssl_certificate_key should be the key file generated when you created the CSR.

Please note, this part is just to update expired SSL certificate so you don’t need to do anything on the key file.

Step3: concatenate the SSL certificate and intermediate certificate

In fact, you need to backup or remove the existing expired domain.crt first and the do concatenate. Just for safe.

cat 29393****.crt gd_bundle-g2-g1.crt >> domain.crt

Step4: restart Nginx

sudo nginx -s reload
Advertisements

Server Protection and Monitor

As we all know, there is a huge DDoS attack recently which influences lots of websites. At first beginning, our server didn’t get influenced by it. But last week, I allow ssh server by password.(In the past, we only allow the user to use the public key to ssh server. But last week, we just want to allow a user to log in simply and fast. We open it temporarily and forget to close it) This week, the server is totally attacked. Anyway, the final problem is that our server is blocked by increasing useless threads and bandwidth is used up. So here I list how I find these problems and how we try to fix it.

Step1: check network status

According to check network status, you will find bandwidth is too high which influences other normal customers to use this server’s resources.

sudo apt-get install nethogs
sudo nethogs
sudo nethogs eth0 eth1

Step2: find exact threads

Except knowing the bandwidth status, you also need to know thread status. By viewing real-time thread status, you will know there are many malicious threads which take too many resources. For my case, I find there are 300 malicious threads which are created every 2 minutes. It is not hard to understand that the final server is slow enough to undertake these increasing malicious threads.

sudo apt-get install htop
htop

Step3: kill useless threads

After known these malicious threads, we need to kill them. In fact, killing them can solve this problem by root cause. Because for now I only know its effect, not the root cause. Luckily we find a bash script which causes it. So I kill this bash script together. Until now, it looks like we already finish everything. But things haven’t done. After 8 hours stable network, the server is attacked again. I can’t ssh into the server. So final solution is to shut down and rebuild the server. So for now, I don’t know the root cause.

sudo kill -9 $(pgrep <useless_threads_main_name>)

Step4: add your own public key to ssh

In order to avoid the attack happens again, I involve public key back. Because I’m sure this attack happened when I open password login.

ssh <user_name>@<server_ip> 'mkdir -p ~/.ssh;cat >> ~/.ssh/authorized_keys' < ~/.ssh/id_rsa.pub

Here id_rsa.pub is your own public key file.

Step5: disable password to ssh

sudo vi /etc/ssh/sshd_config
# change to no to disable tunnelled clear text passwords
PasswordAuthentication no
PubkeyAuthentication yes
service ssh restart

Conclusion:

Using high-level security configuration is needed to avoid this kind of attack. Once this malicious attack happens, the best way is to backup your data as soon as possible and rebuild your server. (During investigation process, I also install several kinds of maldetect tools. I’m trying to use these tools to scan out the malicious scripts/codes/software. But unfortunately, they all failed.)

I still need more knowledge to help me understand and find out the root cause. Keep learning.

Play Framework(12)-template engine

Concept:

Templates are complied as standard Scala functions, following a simple naming convention. If you create a views/Application/index.scala.html template file, it will generate a views.html.Application.index class that has an apply() method.

Special Character :

Scala template uses @ as the single special character. Every time this character is encountered, it indicates the beginning of a dynamic statement. If you want to insert a multi-token statement, explicitly mark it using brackets/curly brackets. Because @ is a special character, you’ll sometimes need to escape it by using @@.

Make sure that { is on the same line with for to indicate that expression continues to next line.

Tips:

A template is like a function, so it needs parameters, which must be declared at the top of the template file.

You can write server side block comments in templates using @@.

Dynamic content parts are escaped according to the template type’s (e.g. HTML or XML) rules. If you want to output a raw content fragment, wrap it in the template content type.

 

Slick (3) – connection pool

Before talking into detailed knowledge about connection pool in Slick, we need to figure out two things: One is about Slick. Slick does not provide a connection pool implementation of its own. The other thing is about JDBC, which not provides asynchronous database driver for JVM. So we need to thread pool in Play Framework application to help improve performance.

1. Add connection pool to Slick:

Event Database contains an AsyncExecutor that manages the thread pool for asynchronous execution of Database I/O Actions. Its size is the main parameter to tune for the best performance of the Database object. It should be set to the value that we would use for the size of the connection pool in traditional, blocking application. For Slick, its default connection pool is HikariCP, which is a “zero-overhead” production-quality connection pool.

import play.api.db.DB
import play.api.Play.current
import slick.driver.MySQLDriver.simple._
object Contexts {
  def withSession[Res](f: Session => Res) = {
    Database.forDataSource(DB.getDataSource(),
      AsyncExecutor(<executor_name>, <num_threads>, <queue_size>)) withSession f
  }
}

2. connection pool configuration

There’re some important default configuration which we need to know. Of course, we can override them to optimize.

# HikariCP connection pool configure
play.db.hikaricp.connectionTimeout=30 seconds
play.db.hikaricp.maxLifetime=30 minutes
play.db.hikaricp.maximumPoolSize=10

3. thread pool vs connection pool

There is dependency between these two pool setting is in maximum attribute.Let us assume that your database can support maximum of 50 connections then it is straight forward to configure the connection pool maximum attribute as 50. But how this setting going to impact thread pool setting? Configure application server thread pool as maximum of 100. In this scenario application server will allow 100 request to be processed simultaneously however database have only 50 connection. So only 50 thread will get connection another 50 thread will fight to get database connection hence connections will be switched between threads frequently that slow down overall application performance.

Just adding database connections will not improve performance, and can compromise availability because of the need to reestablish all the connections during failover.

Let us assume we set thread pool maximum setting same as connection pool maximum setting of 500. Application server will allow 50 thread to be processed simultaneously the remaining thread will be in wait state. All the 50 thread will get database connection immediately hence it will processed quickly.

The above example assumed each thread will use one database connection (may be multiple connections but sequentially); if your application uses two database connections parallels by each thread then configure thread pool maximum setting as half of the connection pool maximum.

Setting the thread pool size too large can cause performance problems because if there are too many concurrent threads, task switching overhead becomes a serious bottleneck. Any more threads than the number of connections available could be wasteful given contention for the connections. Fewer threads will not consume the number of connections available. 

4. number of processor core vs the size of a thread pool

  • More threads mean more memory usage. Each thread requires a thread stack. For recent HotSopt JVMs, the minimum thread stack size is 64KB, and the default can be as much as 1MB. That can be significant. In addition, any thread that is alive is likely to own or share objects in the heap whether or not it is currently runnable. Therefore it is reasonable to expect that more threads mean a larger memory working set.
  • A JVM cannot have more threads actually running than their cores (or hyperthreaded cores) on the execution hardware.

5. Involve connection pool to database querying

def delete(userID: Int): Boolean = Contexts.withSession { implicit session =>
  val users = TableQuery[Users]
  val filterInfo = users.filter(_.id === userID)

  if (filterInfo.exists.run) {
    filterInfo.delete
    true
  } else false
}

6. Reuse session within one logic

We know the more sessions we use, the much easier the connection pool uses up. So within one logic, we suggestion to pass session around to finish one purpose. In order to reuse session, we need to pass session as implicit.

def save(implicit session: Session, traitInfo: TraitInfo): Int = {
  val traits = TableQuery[Traits]
  (traits returning traits.map(_.id)) += traitInfo
}

7. Additional important things to know

Some Concepts on Slick we need to know/understand:

  1. For every database session (withSession blocks), Slick is opening a new connection to the database server.
  2. Session Handling:
    1. The Database object’s withSession method creates a Session, passes it to a given function and closes it afterward. If we use a connection pool, closing the Session returns the connection to the pool.
    2. Only the method actually executing the query in the database requires a Session. The executing methods are made available via implicit conversions.
    3. It is not recommended to handle the lifetime of a Session manually.
  3. All methods that execute a query take an implicit Session value. Of course, you can also pass a session explicit if you prefer.

Basic Knowledge on connection pool:

  1. Connection pools are common in network applications and they’re often tricky to implement. For example, it is often desirable to have timeouts on acquisition from the pool since various clients have different latency requirement.
  2. Pools are simple in principle: we maintain a queue of connections and we satisfy waiters as they come in. With additional synchronization primitives this typically involves keeping two queues: one of waiters (when there are no connections), and one of connections (when there are no waiters).

8. Todo In Future:

There are some points we can optimize.

  1. Slick uses prepared statements wherever possible but it does not cache them on its own. We should therefore enable prepared statement caching in the connection pool’s configuration and select a sufficiently large pool size.

Email Render For different clients

In fact, there is no difference between web front-end development and email development. But if we want to compatible with all email clients, the thing becomes a trouble. Here I list some notes to make the thing a little easier.

  • Tool: litmus
    1. Now more and more developers use Mac as the main laptop to work. If we don’t have all devices, how can we know the final render result before we send out? Here is an online website: https://litmus.com You can use it free feature to get render result on Outlook, iphone6, and Gmail. For me, it is enough. Because most of the problems are coming from Outlook. If I can fix Outlook issue, others are normally ok.
  •  position
    • we’d better use a table to design the whole layout. Note: here the width doesn’t have px .
    1. <table border="0" cellpadding="0" cellspacing="0" width="580" style="background-color: #0290ba;">
  • background image
    • For normal case, we can use the background to do.
    • <td width="100" height="100" style="background: url('someurl');">text</td>
      
      <td background="@bgImage" style="background-size: cover;background-position:50% 50%" bgcolor="#7bceeb" valign="middle">
    • For Outlook, we’d use a different one. This method is good, but if we want to achieve “background-size: cover” effect, we need to add “aspect” to control its resize ratio. (Please note: here the size we use the width’s same size. Normally we should select the larger one between  width and height. ) If not, it will resize the whole original image, it is like “background-size: contain”. Depends on which is your requirement, you need to know exactly which “background-size” you need.
    • <!--[if gte mso 9]>
      <v:rect xmlns:v="urn:schemas-microsoft-com:vml" fill="true" stroke="false" style="width:620px;height:190px;">
      <v:fill type="tile" src="@bgImage" color="#7bceeb" aspect="atmost" size="620pt 620pt" /> 
      <v:textbox inset="0,0,0,0"> 
      <![endif]-->
    • The method above will create a background, but its size is not scalable. If we want a scalable background, we’d better use following method. And your content is between the two codes. So please note: The first method we mentioned above doesn’t need to put content between codes, you just need to put above code before your td or table and then the background will be applied to your next content. But the second method here we talk needs to put your content between the two codes snip.
    • <!--[if gte mso 9]>
      <img src="@bgImage" height="190" width="620" border="0" style="display: block;" />
      <v:rect xmlns:v="urn:schemas-microsoft-com:vml" fill="false" stroke="false" style="position:relative;top:0;left:0;width:620px; height: 190px;">
      <v:textbox inset="0,0,0,0">
      <![endif]-->
    • <!--[if gte mso 9]>
      </v:textbox>
      </v:rect>
      <![endif]-->
    • Until now, the background is ok. But if we want to put overlay above the background, we need to a little adjust the second method. (This case is very important for user experience, because sometimes, if we just put content purely over the background, the background color will impact the content’s final effect. We’d better put a dark overlay over the background. In fact, the dark overlay is between the background and the content)
    • <!--[if gte mso 9]>
      <img src="@bgImage" alt="replace" height="190" width="620" border="0" style="display: block;" />
      <v:rect xmlns:v="urn:schemas-microsoft-com:vml" fill="true" fillcolor="black" stroke="false" style="position:relative;top:0;left:0;width:620px; height: 190px;">
      <v:fill opacity="0.5" />
      <v:textbox inset="0,0,0,0">
      <![endif]-->
    • <!--[if gte mso 9]>
      </v:fill>
      </v:textbox>
      </v:rect>
      <![endif]-->
    • Above method use img to solve  background problem, but its scale image is for the entire image. If you want background-position and background-size applying on the image, you need to use the following method.
    • <!--[if gte mso 9]>
      <v:rect xmlns:v="urn:schemas-microsoft-com:vml" stroke="false" style="width:620px;height:190px; background-repeat:no-repeat; background-position:top center;">
      <v:fill type="frame" color="#181907" opacity="0.49" src="@bgImage" />
      <v:textbox inset="0,0,0,0">
      <![endif]-->
    • <!--[if gte mso 9]>
      </v:textbox></v:fill>
      </v:rect>
      <![endif]-->
  • Margin or padding
    • For Hotmail, it still supports padding-left, padding-right, and padding-bottom. But for Outlook, it doesn’t support any. Here I use a trick to solve it. As I say, it is a trick, so it can’t solve it totally. I add empty space to be as a padding or margin.
    • <!--[if gte mso 9]>
      <tr><td width="620" height="50" align="center" valign="middle"></td></tr>
      <![endif]-->
      
    • Using a negative margin-top on a div inside a td will not have any effect unless the div has any other preceding element neighbors. If you had, for example, an h1 before your div inside the td, you could use margin-top: -10px; on the div to move the div closer to the h1 visually.
  • Float
    • For normal case, we can use this to float text.
    • style="float: right"
    • But for Outlook, we’d better use align to do it.
    • <td width="620" align="center">
      <span style="font-size: 40px; font-weight: bold; text-transform: uppercase; color: #fff;"> @bodyTopic </span>
      </td>
  • display
    • ‘display:none’ is not supported in Outlook. Here is the fixed solution as below.
    • style="display: none; max-height: 0px; font-size: 0px; overflow: hidden; mso-hide: all"
  • border-radius
    • Outlook doesn’t support rounded button, what you can do is to use image as background to implement this. I know it is totally trick but there is no another way to solve it.

 

Play Framework (1) – WebSocket

Even though Play uses async method to communicate with front-end and back-end. But sometimes, we still need to call third-party restful api to do something else. Especially, third-party restful api takes too long time to return data. In this case, it is wasteful to wait there and always ask whether it is ok or not. Good way to handle it is to make use of third-party callback and web socket to deal with this case.

So it is very clear that we have three sides: one is third-party api, the other is our back-end, another is our front-end.

What we need to do is that front-end builds a WebSocket with back-end. And then back-end requests data from third-party api. When third-party api returns data,  back-end sends data back to front-end.

  1. Build a web socket between front-end and back-end.
  2. front-end sends data to back-end
  3. back-end calls third-party api
  4. third-party api returns data back to back-end
  5. back-end returns data back to front-end by web socket

So, there are two routes, one is for web socket, another is for callback. The connection between the two is to store actorRef to keep the bridge. You also needs to ask callback to append special token back in order to figure out this actor.

  • Javascript code to send web socket to build connection between front-end and back-end.
  • var myWebSocket = new WebSocket("ws://<your_domain_name>/<your_ws_route>/");
    myWebSocket.onopen = function() { myWebSocket.send(<your_data>); }; 
    myWebSocket.onmessage = function(event) { alert(event.data); // to render data }; 
    myWebSocket.onclose = function() { console.log("wsconnect close."); };
  • Nginx configuration to build connection. Please note: Here if you don’t configure “

    proxy_read_timeout” attribute, your websocket default connection time is 60 seconds and then it is closed automatically. So here normally I set it as 1d.

  • location /daoApp/websocket/create/ {
      proxy_pass  http://<your_domain_name>;
      proxy_http_version 1.1;
      proxy_set_header Host $host;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
      proxy_read_timeout 1d;
    }
  • Play routes to accept web socket request and another one is to accept callback request
  • POST    /<your_callback_route>/ controllers.WebSocketApp.apiCallback
    GET     /<your_ws_route>/       controllers.WebSocketApp.create
  • And next I have one global variable to store actorRef for each connect between front-end and back-end. For each web socket request, I will store unique key combining the actorRef and trigger call to third-party api. For each callback request, I will to find its mapping actorRef to send data back to front-end.
  • object WebSocketApp extends Controller {
      // remember to build a map to store your actorRef
      // here we use ConcurrentHashMap which is to avoid memory leak in multiple cores device
      var channels = new ConcurrentHashMap[String, ChannelMsg]().asScala
      def apiCallback = Action {
        request =>
          val requestBody = request.body.asFormUrlEncoded
          requestBody match {
            case Some(s) =>
              if (s.contains("parentID")) {
                val parentID = s("parentID").head
                val channelInfo = channels.get(parentID)
                channelInfo match {
                  case Some(info) =>
                    val yourParsedData = <deal_with_data_from_api>
                    actorInfo match {
                      case Some(actor) =>
                        actor ! <your_parse_data>
                        channels.remove(parentID)
                      case None =>
                    }
                  case None =>
                }
              }
            case None =>
          }
          Ok
      }
    
      def create = WebSocket.acceptWithActor[String, String] { request => out =>
        Props(new DAOWSCreateActor(out, request))
      }
    }
    class DAOWSCreateActor(out: ActorRef, request: RequestHeader) extends Actor {
      override def receive = {
        case topicName: String =>
          val queryTokenInfo = <your_send_request_to_third_party>
          // remember to involve your actorRef to channelMsg which will be used to parse actor 
          valchannelMsg = <construct_your_channel_msg>
          // remember to involve your key to callback on post which will be used to find actor back to send data back to front-end
          WebSocketApp.channels.put(<your_key>, channelMsg)
        case _ =>
      }
    }

Play Framework (2) -Security (especially for web application)

Here we talk about how to make our web application much safer. Even though most front-end codes can be detected by any developers, we still can use back-end to protect each request’s security. I will list the method which attackers might be used to hack your system and then I give out basic and simple solution. Here I need to say something in advance: First, the solution here targets play framework. But i think the solution’s idea/view is general for other website framework. Second, because play framework already has multiple versions, i can’t try all of them and here we use 2.3.x . So if you use other play version, please consider how to implement solution in your own version. All in all, I will give out problem first and talk about my solution’s idea, and at last give code snippet to explain idea.

1. problem

we all know front-end uses router to connect with back-end in order to get some data or post data to store. Once the router is recognized by attacker. It is quite easy for other developers to send requests to back-end without requiring to login the system or in website. There are many public tools which can do this thing, like postman, etc.

2. solution

The solution is easy to think out: authentication. The authentication is already greatly used in many places and there are many mature libraries which already provide packaged class/object to call, like social-auth, play2-auth, etc.

But there are too complex, if you want simpler one, you just need to consider how to make sure “Action” is safe in your code. As we all know, each router mapping to back-end is Action, no matter GET or POST. If we can make sure “Action” is a safe action, our router is safe. So we try to re-define a double check Action which needs to check each request’s header whether it contains the authenticated info. If not, we treat this request is not authenticated, the request can’t be finished. For browser, this means the page needs to guide back to login page to force user login or signup. Only when user logins or signs up, we assign the authentication to the user. After the user is authenticated, the other requests are allowed from this user.

Here we list the logic:

  1. user login/signup, back-end will set the user authenticated
  2. user does other requests, back-end will treat it as authenticated
  3. if user not login/signup or already logout, the next request will be treated as unauthenticated, 401 will be returned.

3. code snippet

Define a useraction:

package controllers

import play.api.http.Status
import play.api.mvc._

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

object UserAction extends ActionBuilder[Request] {
  def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
    if (request.session.get("WWW-Authenticate").isDefined)
      block(request)
    else
      Future { Results.Status(Status.UNAUTHORIZED) }
  }
}

Login/signup with an authentication:

Ok(resultInfo).withSession("WWW-Authenticate" -> "user")

Logout:

Ok.withNewSession

Other router using defined useraction:

/**
 * Delete one user back to front-end
 */
def delete = UserAction {
  request => {
      // do your things
    }
  }
}

4. Additional Info

(1) CSRF(cross-site-request-forgery)

Problem: If the attacker uses false info to signup, he/she still can use this authenticated user to do some dangerous things.

Solution: Of course, we can assign different levels of authentication. For example, for admin operations, only use who knows admin’s right or has admin’s authentication, he/she can obtain the operation.

But there is another easy way to solve it: filter.

To allow simple protection for non browser requests, such as requests made through AJAX, Play also supports the following:

  • If an X-Requested-With header is present, Play will consider the request safe. X-Requested-With is added to requests by many popular Javascript libraries, such as jQuery.
  • If a Csrf-Token header with value nocheck is present, or with a valid CSRF token, Play will consider the request safe.

(2) ActionBuilder

Action is just an implementation of ActionBuilder[Request]; we can extend ActionBuilder to use in place of Action as above codes in snippet.

ActionBuilder requires that we implement invokeBlock, which takes two parameters, the first is the incoming request, and the second is the function body, taking Request[A] as a parameter and returning a Future[Result]

block(request) means request processing continues as expected. (Don’t confuse the world “block” to mean the request gets blocked, it is actually executing the code block or function body it was passed earlier)

5. Recommend Links

(1) Here is link about how to use play header to fix CSRF: https://www.playframework.com/documentation/2.3.x/ScalaCsrf 

(2) Action Composition in Play Framework: https://www.playframework.com/documentation/2.3.x/ScalaActionsComposition and http://iankent.uk/2014/02/10/action-composition-in-play-framework/ (this link’s knowledge is a little old, but really useful and completely. And it also provides more integral solution than mine. Strongly suggest to read. )