DIY Guides for AWS

These how-to guides that will help you start an create a simple and cheap server solution that will cost around $20/month. These guides includes:

  • Introduction
  • Domain Name
    • Purchase
    • Configuration (DNS)
    • Transfer from GoDaddy
  • Create and configurure your personal virtual server
    • Remote desktop access
  • Hosting web sites / apps on a virtual machine (Windows Server / IIS)
  • Configure your first small business or personal web site
    • WordPress
      • PHP
      • MySQL
  • Host ASP.NET Web Application
    • IIS
    • SQL Server
  • Send-Receive Emails
    • Outgoing (local smtp / IIS), using:
      • Integrated Windows SMTP Relay Service IIS
      • or hmailserver (preferred)
        • Configuring DKIM for hmailserver
      • or AWS SES (Simple Email Service)
    • Outgoing alternative
    • Incoming (MX, txt, spf, pop, accounts, catch-all, …)
  • SVN Server
  • FTP Server
  • Network and Security
    • Firewall
    • private and public IP
  • Monitoring
  • Troubleshooting
  • etc

You can get all that running, for about $20/month, on a EC2 T2.Micro Virtual Machine.

Let’s begin with…

Getting Started with Amazon AWS.

Retrieve performance on Killer E2500 network adapter

Recently (since end of 2022), I had issues after running Windows Update on my MSI Laptop GS63 7RD, with network adapter Killer E2500.

After running update, my network becomes very slow.

Every time, I noticed that, during the update, 2 drivers or software were changed: These are, Intel SoftwareComponent, and Rivet Networks driver.

I was able to get my performance back, by removing the new network adapter drivers, that restores the original one. But, on the next update, these new drivers are reinstalled.

I finally found a method to retrieve the performance and keep the new driver, so it will not be replaced on the next update.

What you need to do, is to stop and disable the Killer or River services related to that driver. These services try to help you, by detecting issues on network (I think). But, in fact, they doesn’t help at all!

Select theses windows services, stop them, and disable them to prevent them to start on reboot.

That’s all!

Fix “This server supports TLS 1.0 and TLS 1.1” on Qualys SSLlabs test

Over the years, we published some popular articles on how to get the best score on SSLLabs tests.

This year, we’re back on that popular issue, that can now be solved. In January 2020, Qualys changed their test to give note “B” when TLS 1.0 and 1.1 are still supported.

By default, IIS server gives that result on Qualys SSLLabs test.

Even in the last IIS version (10), these protocols they are still enabled by default. (list of default protocols status)

Now, this is what you need to do to avoid that validation message: “This server supports TLS 1.0 and TLS 1.1. Grade capped to B.”

How to fix that on IIS: (Link on microsoft article)

For TLS 1.0: (link on Microsoft article)
For TLS 1.1: (link)

To avoid complexe registry edit, you can copy-paste the following config in a file called “disable-tls-10-11.reg”, created using notepad. then double-click on it.

Content of the file:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server]
"Enabled"=dword:00000000

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Server]
"Enabled"=dword:00000000

Save it, and double-click on it, and accept all confirmations, to add these settings to your registry database.

Then reboot your computer, and run your SSL test again. Grade A reached!

new String replaceAll Javascript not so powerful

There’s a new javascript function in the String prototype, called replaceAll.

We all tried the native replace function, to find that it only replace the first occurrence, and we have to use a regex to really replace all, like this:
“the blue fox”.replace(/blue/g, “red”);

Now, the replaceAll does what we hope, by replacing all “string1” with “string2”, in the whole string instance, returning a copy of it.

But, in the meantime, lots of people tried to create their own replaceAll function, and one of them was to use the split / join trick. We found that it’s also very powerful when we need to manage large strings, or with a large amount of strings to convert.

So, I tried to see if I can replace all my split-join usage, with the new replaceAll.
And, the answer is NO!
Instead, I will make sure I never use the new replaceall, and I’ll keep my old custom function.

The split-join is, depending on the length of the input / find / replaceBy variables, up to 5 times faster in the tests I did.
Sometimes, it’s the same speed, but most of the time, it’s faster. And, in Chrome 85, it’s never slower.

Test code:

    <button onclick="test_replaceAll();">replaceAll</button>
    <button onclick="test_split();">split</button>
    <script>
      console.clear()
      var i = 25;
      var s = "asdf".repeat(i * 100000);
      var sFrom = "sd";
      var sTo = "z".repeat(i);

      function test_replaceAll(){
        var t0 = (new Date()).getTime();
        var t1 = s.replaceAll(sFrom, sTo);
        console.log("t1", t1.length, (new Date()).getTime() - t0);
      }

      function test_split(){
        var t0 = (new Date()).getTime();
        var t2 = s.split(sFrom).join(sTo);
        console.log("t2", t2.length, (new Date()).getTime() - t0);
      }
    </script>

Look at these results: First 5 are “replace”, last 5 are “split/join”

replaceAll: 750ms
split/join: 250ms

There’s no doubt that the split/join method is still the fastest.

But, if you need to use “regex” instead, now the replaceAll is the one to use.

High performance JavaScript htmlEncode

I recently had to encode lot of strings to HTML in client-side javascript.  There’s a lot of find-replace procedures we can find all over the web, but I think that the most reliable way to encode string is to use the browser itself.

One very easy method to encode a string, that we find everywhere, is this one: 

function htmlEncode(_s){
  return $("<span />").text(_s).html()
}

If we use that quick jQuery function, we know that the result is totally safe, by allowing the browser to do the job on our behalf.

But, using the DOM is sometimes the cause of a slow application…
Does this method is reliable if we need to convert thousands of strings?

I did the test, by repeating the conversion 100000 times.

The previous function, creates a new “span” on every call, and modify the innerHTML of it.

Chrome console “performance monitor” shows that there are 3 DOM nodes created on each call. It takes an average of 2200 ms to run the loop, and generates lots of garbage collection to remove these old DOM items.

Take 2

So, let’s try to re-use the previous span instead without re-creating it.

var $span;
function htmlEncode(_s){
   $span = $span || $('<span />');
   return $span.text(_s).html();
}

This time, on each call, 2 DOM nodes instead of 3 are created.
And, the average time goes down to 1600 ms instead of 2200.

Take 3

Then, I tried to see what jQuery does, to see if it’s possible to re-use the inner text objects that are re-created on each call.

Now, try that 100% non-jquery method. (That you can achieve by using jquery and editing the childNodes directlly…)

var spn, txt;
function htmlEncode(_s){
   if (!spn) {
      spn = document.createElement("span");
      txt = document.createTextNode("");
      spn.appendChild(txt);
   }
   txt.data = _s;
   return spn.innerHTML;
}

That final version of our custom htmlEncode function looks very powerful!

Now, 0 nodes are created on each loop (3 on the first call), we always re-use the same 3 nodes.
And, the loop time is now 100 ms, with absolutely no garbage collection!

Summary

Look at these analysis from the Chrome console.

You can try it by yourself on that demo page I used to generate the previous tests.

How to generate a strong password using Google Chrome

There’s a good password generator embedded into Google Chrome. It appear when you create a login in the “input type password” fields.

But, if you need to generate a password for something else, e.g. mysql database user, there’s no way I found to use it from the menu or somewhere else.

That’s why I create that “fake” signup form, just to use the “generate password” chrome feature.

uid:
pwd:

Save it in in your bookmarks and enjoy!

Split string SQL Server

Being able to do a simple split on a string in SQL server have always been a real pain.

With SQL Server 2016, Microsoft introduces the new “STRING_SPLIT” function.

Easy to call, but very limited.

select * from string_split('s,p,l,i,t', ',')

returns a 5 row, 1 for each letter. Just values, no position.

That’s why I added some features to that function, with the addition of the “position” in the resultset.

CREATE OR ALTER FUNCTION string_split_position
(
	@input nvarchar(MAX),
	@separator nvarchar(1)
)  
RETURNS @RtnValue table 
(
	[value] nvarchar(max),
	position int identity
) 
AS  
BEGIN 	
	INSERT INTO @RtnValue ([value])
	SELECT [value] FROM string_split(@input, @separator)
	Return
END;
GO
SELECT * FROM string_split_position('s,p,l,i,t', ',')
valueposition
s1
p2
l3
i4
t5

Finally, I also create an “inline” function, used to get 1-based nth character directly from a string.

CREATE OR ALTER FUNCTION string_split_inline
(
	@input nvarchar(MAX),
	@separator nvarchar(1),
	@position int
)
RETURNS nvarchar(max)
AS
BEGIN
	DECLARE @value nvarchar(max)
	select @value = ssp.[value]
	from string_split_position(@input, @separator) ssp
	where ssp.position = @position
	RETURN @value
END
GO
SELECT dbo.string_split_inline('s,p,l,i,t', ',', 3) AS third
returns 'l'

If you have ideas to make these functions more powerful, do not hesitate to share them with us in the comments.

How-to allow AWS IAM users access to Billing Dashboard

You found that page because you tried to create an IAM user, and allow Billing dashboard access.

You set it all the required permissions, like “AdministratorAccess” or “Billing”, and it didn’t work.

Then, you also tried to add an “inline policy”, by selecting “Billing” service, + “All Billing Actions” (aws-portal:*), and it’s still not working.

When using that IAM user to access billing dashboard, you always see that message:
“You Need Permissions – You don’t have permission to access billing information for this account. Contact your AWS administrator if you need help. If you are an AWS administrator, you can provide permissions for your users or groups by making sure that (1) this account allows IAM and federated users to access billing information and (2) you have the required IAM permissions.”

You follow provided help link, and it doesn’t help, they only tell you again and again that you should enable billing access to iam users. But, like most of AWS documentation, they never tell you HOW to do that easily!

I will tell you, because I lost hours to find it, and I want to help someone who have the same issue.

Login with your “root” account. Then, go to “my account” menu on top right, or follow that link: “My Account“.

On that page, search for “IAM User and Role Access to Billing Information“.

There’s a warning in that section: “IAM user/role access to billing information is deactivated“.

Finally, all you need is to click “Edit”, check the box, hit Update, and you’re done!

Calibre is slow, not your Kindle.

I recently decided to move from Kobo to Kindle. Because I have a Prime subscription, that give free books, from their “Prime Reading” offer. Also because there was a good deal on Boxing Day, we could get it for only $60.

They call it the “All-New Kindle”, something like a new version of the previous Paper White I think, without water resistance…

To manage Kobo files, I always used the Adobe Digital Editions software, who works great, fast and easy to use. It is compatible with all e-readers in the world, except Kindle.

Then, I thought Amazon did an app like that. They did an app called Send To Kindle, works really find with pdf and some other formats, but not Epub files.

So, after a few research, you found that Calibre app, that can help you copy these files to your Kindle.

I tried it. Added my Epub to the library, and hit the “send to device” button. What? That is terribly slow, and it crashed a lot of times. I thought, like others on the internet, that the kindle device or its USB port is so so slow and that’s the reason calibre is slow.

But, the problem is not the kindle. It’s calibre!

The good way to send your Epub to kindle, using the Calibre app, is to do a 2-step process.

First, select your files, click “Convert”, and choose “Mobi” format on the top right dropdown.

Then, wait. And wait again. That process is very long.

When it’s complete, select all your files again, and now hit Send to Device button. Now, it will be very fast without crashing.

I think Calibre have lots of trouble handing conversion + usb transfert at the same time.

You can see the running jobs by clicking the “Jobs” label on the lower right corner of Calibre app.

Now, restart your Kindle device, you will see all your uploaded content appear one by one for about a minute.

That said, Calibre is an easy to use, free well done app, that help us get control over Kindle devices. That’s why all Calibre users should hit the “Support Calibre” link and donate something, to encourage that developer to continue supporting that app for a long time.

How to export all Route53 DNS zones entries

I recently had to export all Route53 DNS entries, just to do some cleanup of them. I was surprised that there is no “official” way to export them all from the AWS console!
I found the cli53 tool, but it doesn’t do exactly what I need.

So, I decided to write my own powershell script. I share it with you, I hope it may help!

Feel free to send me your suggestions to make it better!

$zones = Get-R53HostedZoneList | select name,id,ResourceRecordSetCount | sort -Property name

foreach ($zone in $zones) {
    [string]::Format(“[{0}] [{1}] ({2})”,$zone.Name, $zone.Id, $zone.ResourceRecordSetCount)
    $recordsets = Get-R53ResourceRecordSet -HostedZoneId $zone.id 
    $recordsets = $recordsets.ResourceRecordSets | sort -Property type # | where type -EQ 'a'
    foreach ($rs in $recordsets){              
        [string]::Format(“`n[{0}] [{1}] ({2})”,$rs.type, $rs.name, $rs.ResourceRecords.Count)
        foreach ($record in $rs.ResourceRecords){
            [string]::Format("   {0}", $record.Value)
        }
    }
    "`n-----------------------------`n"
}