Saturday, 25 July 2015

SPApplicationAuthenticationModule: There is no Authorization header, can't try to perform application authentication.

This week we had an interesting issue with one of our SharePoint servers.

We have a two server farm, both servers are full servers that had been installed a couple of months ago and as far as I was aware both servers had been tested, so I was little bit surprised when the farm was tested in anger and we were getting a roughly ~20% failure rate in a process that uploads a document to SharePoint.

After a bit of digging we found that it was due to one of the SharePoint servers. 

We could not even log in to any of sites hosted on the farm if we hit this server. We simply would get a 401 unauthorized error. 

I know we also seem to have a load balancing issue but that's for another day.

Perhaps, unsurprisingly the logs did not show much, so I bumped them up to verbose and here's what we found:

Claims Authentication        SPIisWebServiceAuthorizationManager: Using identity '0#.w|dev\svc-spadm' as the actor identity.
Topology                     WcfReceiveRequest: LocalAddress: 'http://sp02.dev.local:32843/934e0061c6a94255b9ab9e6f2ba45325/SearchService.svc' Channel: 'System.ServiceModel.Channels.ServiceChannel' Action: 'http://tempuri.org/ISearchHealthMonitoringServiceApplication/GetQueryHealthMonitoringSettingsForComponents' MessageId: 'urn:uuid:f00ca305-b1d5-4454-85fa-5f83e7094518'
Monitoring                   Leaving Monitored Scope (ExecuteWcfServerOperation). Execution Time=154.973746663333
Monitoring                   Entering monitored scope (Request (GET:https://<site>)). Parent No
Logging Correlation Data     Name=Request (GET:https://<site>)
Claims Authentication        SPTokenCache.ReadTokenXml: Successfully read token XML ''.
Application Authentication   SPApplicationAuthenticationModule: There is no Authorization header, can't try to perform application authentication.
Authentication Authorization Non-OAuth request. IsAuthenticated=False, UserIdentityName=, ClaimsCount=0
Claims Authentication        Claims Windows Sign-In: Sending 401 for request 'https://<site>' because the user is not authenticated and resource requires authentication.
Monitoring                   Leaving Monitored Scope (Request (GET:https://<site>)). Execution Time=3.75103539695688
Claims Authentication        SPFederationAuthenticationModule.OnEndRequest: User was being redirected to authenticate.
Claims Authentication        Claims Windows Sign-In: Sending 401 for request 'https://<site>' because the user is not authenticated and resource requires authentication.

Clearly, It's not able to authenticate but why? I thought that the lack of authorization header was the clue but nothing I found in Google helped me and then I sort of had a flash of inspiration and decided to check whether the site had Windows Authentication enabled.

Bingo!!!!!  Windows Authentication is Disabled, no wonder nobody could log in :)


After I enabled it and restarted IIS, the second server started working :)

I didn't install SharePoint on these servers and I don't really have that much experience with SharePoint so I'm entirely sure who to blame here, our guys or Microsoft, but it seems to me that since one of the big things with Microsoft is integration with AD, it's just a bit daft that it doesn't turn Windows Authentication on for the SharePoint site by default. 

Maybe it does and it's something that we did.

At any rate, hope this helps.

Monday, 20 July 2015

Edit C# config file with PowerShell

So today we changed the organization name, too long to explain and all the external apps needed to have their app.config changed to reflect this change. This was across several environments so I thought it would probably be quicker to write a quick script to do it.

The script works for multiple files because they are on subfolders of a common folder, e.g.

Mycompany --> My App 1
                   --> My App 2
                   --> My App 3

It will of course work from say, c:, if you have your apps in different places but it might take a while to run. It will not work if they are in different drives though.

Here's the script:

param ($path, $keyname, $value)

if (-not($Path))
{
 write-host "Path is a mandatory parameter"
 break;
}

if (-not($keyname))
{
 write-host "KeyName is a mandatory parameter"
 break;
}

if (-not($value))
{
 write-host "value is a mandatory parameter"
 break;
}

$configfiles = ls -Path $path -Recurse -Include *config

foreach ($config in $configfiles)
{
 $doc = (Get-Content $config) -as [Xml]
 $obj = $doc.configuration.appSettings.add | where {$_.Key -eq $keyname}
 $obj.value = $value
 $doc.save($config)
}
Assuming the script has been named ChangeConfigFile.ps1, it can be invoked like this:
 ChangeConfigFile.ps1 -path "c:\program files\Apps\" -keyname "Organization" -value "NewOrg"

Saturday, 11 July 2015

Configure MS Dynamics CRM 2011/2013/2015 to use multiple Report Servers (SSRS)

This week I've had quite a bit of fun turning the resilience up to 11 for our production environment of MS Dynamics CRM 2013.

In this post I will discuss how to configure Ms Dynamics CRM 2013 to use multiple SSRS servers, thus ensuring that reporting functionality is as resilient as the rest of the system.

In order to achieve this we need to make changes to AD, the SSRS configuration and finally MS Dynamics CRM. 

It's worth pointing out that this could well be overkill for your system, and to a certain extent it is for ours, but the whole architecture must be resilient is the diktat from above so ...

Pre-Requisites:

  • 1 x Load Balancer (Distributing traffic to SSRS Servers on correct port, normally 80).
  • 1 x VIP.
  • 1 x DNS Record (For VIP above).
  • 2+ x SSRS Servers in a scale out deployment.
  • SSRS configured to use a domain account.
  • Permissions to set SPNs on your domain and edit at least ssrs service account.

My Setup:

DNS record is: CRMReports.dev.local
SSRS Service Account:  dev\svc-ssrs

1. Active Directory

The first thing to do is to set up an Service Name Principal for the account that's running the SSRS service, which can be done with the following commands:
setspn -S HTTP/<VIP FQDN> <SSRS Service account>
setspn -S HTTP/<VIP Name> <SSRS Service account>
So in my case:
setspn -S HTTP/CRMReports.dev.local dev\svc-ssrs
setspn -S HTTP/CRMReports dev\svc-ssrs
The next thing is to ensure that the account is enabled for delegation, so from Active Directory Users and Computers console.


Note that the delegation tab will only appear after an SPN has been set up for that account.

2. SSRS

The first thing to do in the report server, is to enable Kerberos authentication, which can be done by editing the rsreportserver.config file. This file is normally found in this directory: C:\Program Files\Microsoft SQL Server\MSRS11.MSSQLSERVER\Reporting Services\ReportServer\

Look for the Authentication section and enable Kerberos and Negotiate as below (I've commented out NTLM in case I wanted to go back)
<Authentication>
  <AuthenticationTypes>
   <RSWindowsKerberos/>
   <RSWindowsNegotiate/>
   <!--<RSWindowsNTLM/>-->
  </AuthenticationTypes>
  <RSWindowsExtendedProtectionLevel>Off</RSWindowsExtendedProtectionLevel>
  <RSWindowsExtendedProtectionScenario>Proxy</RSWindowsExtendedProtectionScenario>
  <EnableAuthPersistence>true</EnableAuthPersistence>
 </Authentication>
From the Reporting Services Configuration Manager, Click on Web Service URL and then click on Advanced


Click on Add as highlighted.


Enter the host header name, which will be the DNS Record for the VIP, in my case: crmreports.dev.local and click OK to accept.



Repeat this process for the Report Manager Url.

Once done repeat all steps on section 2 on the other report servers.

3. MS Dynamics CRM

The process is relatively simple and it involves editing the organization to point to the new report server dns, i.e. crmreports.dev.local in my case.

From the Deployment Manager, select organization and Disable your organization(s).


Click Edit Organization.


Set the new report server Url.


 Ensure that all checks are ok.


Congratulations, you now have a resilient reporting service for MS Dynamics CRM.

Saturday, 30 May 2015

MOOC done right - Embedded Systems - Shape the World

A few years back I signed up to edX and at time there weren't that many courses available so after the initial excitement of being able to do MIT courses died down, my account was dormant for quite a while, more on this later, until last year I decided to try to learn Python and rather than using LTCTHW or Code Academy, I thought I would try a Python course instead.

A few weeks after I got an email alerting me to other courses that might be of interest and in this email was one that sounded really interesting:
Embedded Systems - Shape the World - UTAustinX -  UT.6.02x
I signed up immediately.

Although the course can be completed without an embedded system, it is, of course, recommended that one is used. Buying instructions for the recommend kit (TI Tiva LaunchPad and some bits and bobs) are provided and not just for the USA. This I found a really nice detail, as I can imagine that probably the majority of people taking the course were not in the USA and it's really one of the many examples of the kind of involvement and enthusiasm that the staff exudes.

My main problem with MOOCs so far has been a combination of lack of motivation, I find it hard to follow through on a topic that, while interesting, might not be applicable for work, current or future, or even daily life and this is not to say that I only learn stuff that's useful, I don't, my head is filled with objectively useless facts, such as the Band Gap of GaAs being ~ 1.42eV (I did not look it up) or Juan Manuel Fangio having won almost half of all the F1 races he participated in or one of my favourite words, biblioclasm

The other reason, and this is probably, the main reason, is lack of time. A lot of the courses suggest a 10-15 hour weekly commitment, this might not sound like much, and in fairness it isn't, most of the time, but some times it is and this is where the Embedded Systems - Shape the World course gets it completely, and absolutely right. The first seven lessons were available when the course started, and the most of rest of content was made available shortly afterwards, so that effectively two weeks after the course started 85+% of the course materials and labs were available.

This is completely at odds with the way that most courses release their material, which is done on an almost weekly basis, with homework(s) due almost on a weekly basis. I find this terribly disappointing. What is the point of doing a course online when you have to basically do it at a pace set for you?  I appreciate that I'm doing it from the comfort of my home but even so this is very likely a major contributory factor to the really poor completion rates in MOOCs. Although I'm not doing the courses for the grades, it's always motivating to be able to get a good grade and the course runs on a very tight schedule a busy week at work or trip can prevent keeping up with the course schedule.

I don't have a CS degree and I've had a interest in low-level programming for a while now, but I've never really taken the time to explore this in any detail as I've always found it pretty daunting, but in the course concepts ranging from CPU instructions and registers to  interrupts and device drivers are explained in a simple and accessible manner. 

In fact, it is explained in such a manner that it's made me lose some of the awe for the guys and gals doing the low-level stuff. I realize that this is silly, as the drivers that are part of the course are extremely simply but it feels as if a veil has been lifted and beneath it, the truth has been revealed.

Instructions on how to get started, install IDE, drivers and TeXas software are provided and I found them easy enough to follow. Those of you out there without a Windows machine might grumble at the lack of direct support, there are instructions on how to the install from virtualization software from a Mac. I guess the authors assume that if you're using Linux you don't need any help getting a hypervisor running :)

All labs have a skeleton project, for Keil's ┬Ávision IDE and a simulation board, which allows the code to be tested before deploying it to the physical board. I often found that working code in the simulation board would fail when deployed to the physical board. This annoyed me a bit at first, but in reality this is no different from the good old:
Well, it works on my machine.
Generally speaking the code was not robust enough and it needed tweaking. I imagine that there are probably more sophisticated simulators available, but the cost is likely to be prohibitive. This is not unlike apps for the myriad Android phones out there.

One thing that was quite surprising at first, although it makes sense since we're are so close to the bare metal, is the way everything is referred to by memory address. For instance, if an application needs to use bits 0 and 1 of Port E, this required knowing the exact address of these bits. Thankfully, these were provided on the skeleton projects but they can also be looked up on the spec sheets. This is, incidentally, an invaluable skill due to large catalogue of systems and components out there.

This is a very simple program, that flashes an LED that's connected to bit 1 of Port E, based on whether a switch connected to bit 0 of PORT E is pressed, and I think it illustrates the point above. Also note, how the delay function counts, effectively, the number of cycles.

#define GPIO_PORTE_DATA_R       (*((volatile unsigned long *)0x400243FC))

int main(void){ 
 while(1){    
 Delay1ms(100);
 if( GPIO_PORTE_DATA_R&0x01){
  //Let's flip it (Bit 1)
  GPIO_PORTE_DATA_R^=0x02;
 }
 else{
  //Lusisti satis,edisti satis,atque bibisti,tempus abire tibi est
  GPIO_PORTE_DATA_R |=0x02;   
 }
  }

void Delay1ms(unsigned long msec){
        long cyclesPerMs = 15933;
 long counter = cyclesPerMs * msec;
 while (counter > 0){
  counter--;
 }
}
}

I've removed the initialization routine, which in essence, gets the physical board running and activates the various ports as needed. I found quite a few of my issues on the physical board where down to issues in the initialization routine, so it's by no means trivial.

The gradual increase in complexity of the physical circuits that needed to be built was very finely tuned. Chapter 8, finally required a circuit to be build, not just using the TI Tiva LaunchPad and it was really nerve racking, I don't really know why, as I think it was only £20 worth of kit, but there were diagrams available and enough warnings regarding what to do and more importantly what not to do, that I built the circuit without any issues. This, actually, ended up becoming the most enjoyable activity of the course, the actual building of the circuits. 

One of the hardest labs, was chapter 10, where a Finite State Machine is used to model a simplified traffic light system for an intersection. I actually really enjoyed this lab even if it took quite a bit of pen and paper to get the design right in the first place. Also, one of my better pictures :). The switches (yellow parts in the middle of the breadboard) model a sensor that detects cars or pedestrians.

Chapter 10 - Modeled  Intersection's Traffic Light System

Chapter 10 - Real System. 
This is not a great picture, but it shows the TI Tiva LaunchPad interfacing with the Nokia 5110 screen. In Chapter 14, an ADC was used for to measure distances. This works by moving the slide potentiometer, measuring the changes in voltage, which can then be converted to a distance, after suitable calibration.
Chapter 14 - Measuring Gauge
In the penultimate chapter of the course, all that was learned during the course is put together on a sort of final project: a games console. This involved designing the game and then putting together the circuit to build it. Although it might sound daunting as usual there was a lot of help in the form of skeleton code. The hardware part, was relatively simple in that it consisted in putting all that had been learned previously to use. An interesting exercise, you can see the results, not mine, I was too late, here.

The last chapter of the course, involved the Internet of Things, which I have to confess, I haven't done yet, as I've procrastinated on getting the WiFi booster pack for the Launchpad and this brings me to another issue with most other courses: The graders

In other courses, I've done these became inactive when the course becomes inactive and, to be fair, it's the same with this course, but there is a massive difference, the graders in this course work by checking a hash (The hash is computed by the grader software that is run in the local machine) and thus, it is entirely possible to check that your programs work as intended regardless of the course status, this is very welcomed novelty for me and I don't know why this is not the case for more courses.

I should point out that the last chapter does require access to a server, which to be fair could've been mocked to allow offline access. The server is still up 2+ weeks after the course ended.

This post has gone on for far longer than I originally intended and I haven't even talked about Electronics, which is a pretty important part of the course, but I  will stop here.

I would like to end the post by thanking the staff on the course and particularly Dr Valvano and Dr Yerraballi, for making this course very accessible, really enjoyable and tremendously educational.

I really hope that a more advanced course is made available by Dr Valvano and Dr Yerraballi, at some point in the near future.

This post doesn't do the course justice, go on, just go and take it, you will enjoy it.

Tuesday, 26 May 2015

Create Relying Party Trust for Microsoft Dynamics CRM from Powershell

I've configured Claims based authentication and IFD for MS Dynamics CRM more times than I care to remember and every time I do it manually, on the basis that it just doesn't take that long, which is true but it's also very tedious, so I spent some time creating a script to create the Relying Party Trust needed for MS Dynamics CRM claims based authentication and IFD to work. Obligatory XKCD.

I've only tried this script with ADFS 3.0 and MS Dynamics CRM 2015, but it should work for MS Dynamics CRM 2013 as well.

It's also possible to pass a file with the claims, using the IssuanceTransformRulesFile and IssuanceAuthorizationRules flags instead for the Add-AdfsRelyingPartyTrust command.

The script should be run after MS Dynamics CRM has been configured for Claims based authentication from the ADFS server.

The script can be also used to create the Relying Party trust for an Internet Facing Deployment and again it needs to be run after IFD has been configured in MS Dynamics CRM.

param ([string]$Name, [string]$Identifier)

if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
{
    Write-Warning "You do not have Administrator rights to run this script!`nPlease re-run this script as an Administrator!"
    break
}

if (-not($Name))
{
 Write-Host "Name is a mandatory parameter. This should be the name of the Relying Party Trust"
 break
}

if (-not($Identifier))
{
 Write-Host "Identifier is a mandatory parameter. This will normally be of the form: https://<fqdn crm>/"
 break
}

$Identifier = $Identifier.Trim("/")

#These are the Transform Rules needed for CRM to work.
$transformRules='@RuleTemplate = "PassThroughClaims"
@RuleName = "Pass through UPN"
c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"]
 => issue(claim = c);

@RuleTemplate = "PassThroughClaims"
@RuleName = "Pass through primary SID"
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid"]
 => issue(claim = c);

@RuleTemplate = "MapClaims"
@RuleName = "Transform Windows Account name to Name"
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"]
 => issue(Type = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer, Value = c.Value, ValueType = c.ValueType);'

#A single Authorization Rule, i.e. let everybody thru. Could tie down further if needed.
$authRules='@RuleTemplate = "AllowAllAuthzRule"
 => issue(Type = "http://schemas.microsoft.com/authorization/claims/permit",
Value = "true");'

#Copied and pasted this from a CRM 2011/ADFS 2.1 RPT
$imperRules ='c:[Type =="http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid", Issuer =~"^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$" ] => issue(store="_ProxyCredentialStore",types=("http://schemas.microsoft.com/authorization/claims/permit"),query="isProxySid({0})", param=c.Value );c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid",Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$" ] => issue(store="_ProxyCredentialStore",types=("http://schemas.microsoft.com/authorization/claims/permit"),query="isProxySid({0})", param=c.Value );c:[Type =="http://schemas.microsoft.com/ws/2008/06/identity/claims/proxytrustid", Issuer=~ "^SELF AUTHORITY$" ] => issue(store="_ProxyCredentialStore",types=("http://schemas.microsoft.com/authorization/claims/permit"),query="isProxyTrustProvisioned({0})", param=c.Value );'

Add-AdfsRelyingPartyTrust -Name $Name -Identifier $Identifier -IssuanceTransformRules $transformRules -IssuanceAuthorizationRules $authRules -ImpersonationAuthorizationRules $imperRules

Set-AdfsRelyingPartyTrust -TargetName $Name -MetadataUrl $($Identifier + "/FederationMetadata/2007-06/FederationMetadata.xml") -MonitoringEnabled $true -AutoUpdateEnabled $true

Update-ADFSRelyingPartyTrust -TargetName $Name
This is what I ran to create the relying party trust for Claims based authentication:

 .\CRMRPT.ps1 -Name "crm2015 - CBA" -Identifier "https://crm2015.dev.local/" 

and this tocreate the relying party trust for IFD:

 .\CRMRPT.ps1 -Name "crm2015 - IFD" -Identifier "https://auth.dev.local/"

Sunday, 17 May 2015

Cashless society N=1

A couple of weeks ago I read an article regarding a new law in Denmark that will effectively make cash not legal tender anymore. In other words, business will not be obliged to accept cash as payment.

To me this seems fairly sensible, I really hate paying by cash, in fact I occasionally find myself struggling to remember the pin number of my debit card as I use it so rarely, so I thought I would try to analyze my cash use. The simplest way of doing this is by looking at cash withdrawals from my bank account.

I decided to have a look at what data I could use from my banks online site and was a little bit disappointed to find that they only provide the last 12 months, I could request older data but it would be printed so I decided to stick to 12 months.

This is the raw data.

As I suspected, there seems to be a decrease in the frequency of cash withdrawals, but the linear fit is pretty poor due to the various outliers.

I did a little bit of thinking and I realized that the March and September outliers are due to leaving dos from people at work and the June one was due to buying some stuff for my girlfriend at Vintage Fair. 

I decided to plot the data again but this time without the outliers.

The trend line, just a linear fit, shows a much better fit than the raw data as is to be expected.

I can easily see this trend holding true, i.e. I will continue to visit the ATM less often, due to the increasing acceptance of contactless payments and its limit being raised to £30 in September.

Friday, 15 May 2015

I Don’t Always Test My Code. But When I Do I Do It In Production

I honestly never I thought I would need to post this:

Unable to Navigate to external domain (auth endpoint) in MS Dynamics CRM 2013/2015 IFD

The standard practice for my company when deploying web servers is to use a host header, which probably made sense at some point but it surely made for an interesting Friday.

I'm tired, so I will just present the facts: If you are configuring IFD and can't get to the external domain endpoint, the problem might be that you have a host header for your https binding.

The external domain endpoint is normally: https://auth.adomain.com/FederationMetadata/2007-06/FederationMetadata.xml and is the last step on the configure IFD wizard.


Ensure that IIS is configured without a host header for the https binding:


Friday, 8 May 2015

ExpectedException Failures in MSTest?

This morning I got an automated email alerting me of a failed build.

Excerpt from Jenkins

Results               Top Level Tests
-------               ---------------
Failed                SecurePasswordTest.EncryptDecryptFailure
Failed                SecurePasswordTest.EncryptDecryptFailureSecureString
Passed               SecurePasswordTest.EncryptDecryptSuccess
Passed               SecurePasswordTest.EncryptDecryptSuccessSecureString
2/4 test(s) Passed, 2 Failed

This is one of the failing tests:

[TestMethod]
[ExpectedException(typeof(System.Security.Cryptography.CryptographicException))]
public void EncryptDecryptFailureSecureString()
{
    var password = DateTime.Now.Ticks.ToString();
    var encryptedPasswordRandom = Convert.ToBase64String(Encoding.ASCII.GetBytes(password));
    var encrypted = SecurePassword.Encrypt(SecurePassword.ToSecureString(password));
    var decrypted = SecurePassword.ToInsecureString(SecurePassword.DecryptString(encryptedPasswordRandom));
}
I ran the tests from my machine and it worked fine. I tried from the server and it worked ....

At this point I remembered that a second build server had been brought online, as some tests runs were taking 2-3 hours, in any case. I checked the other server and I could reproduce the issue, in other words, the test failed there, but why?

Build Server #2 did not have Visual Studio 2013 Shell installed, after I installed it, it started working correctly.

It is rather strange that this happened in the first place and I'm not sure that this is actually related to the ExpectedException attribute, the type of exception or what exactly.

At any rate, hopefully it helps somebody out some day.

Saturday, 2 May 2015

Squid, Azure and beating youtube's regional filter

Every so often I try to watch videos on YouTube that are not available for my region/country (UK) and normally I can easily find an alternative that is available for the UK but last week I thought, why not just use a proxy?.

I have an MSDN subscription, which among other things, gives me £100 of Azure credit a month, so I thought I'd use some of the credit for this.

I provisioned a A0 OpenLogic 7.0 box and I got started. If you're wondering the cost for a linux A0 instance is £0.0011/hr ~ £8 a month and bandwidth is £0.08 per GB (first 5GB are free).
  1. Install Squid

  2. sudo yum -y install squid

  3. Add allowed IP addresses

  4. sudo vi /etc/squid/squid.conf

    # Example rule allowing access from your local networks.
    # Adapt to list your (internal) IP networks from where browsing
    # should be allowed
    acl localnet src 10.0.0.0/8     # RFC1918 possible internal network
    acl localnet src 172.16.0.0/12  # RFC1918 possible internal network
    acl localnet src 192.168.0.0/16 # RFC1918 possible internal network
    acl localnet src fc00::/7       # RFC 4193 local private network range
    acl localnet src fe80::/10      # RFC 4291 link-local (directly plugged) machine  s

    acl work src  111.111.111.0/24
    acl home src  111.111.111.111

    # INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS

    http_access allow work
    http_access allow home


  5. Enable IP Forwarding by editing sysctl.conf file.

  6. sudo vi /etc/sysctl.conf
    Add the following to file: net.ipv4.ip_forward = 1
    sudo sysctl -p /etc/sysctl.conf


  7. Enable and start Squid

  8. systemctl enable squid
    systemctl start squid


Now we need to open the firewall in Azure for the box, Squid listens, by default on port 3128 and configure your browser to use this proxy ... Bye, Bye dreaded: The uploader has not made this video available in your country.

It's worth pointing out that this doesn't work for all websites, see my post about a setting up a VPN server on AWS if you want to a VPN server. Azure doesn't support GRE protocol 47, so it's SSL VPNs only on Azure.