Friday, December 12, 2008

Response.Redirect in UpdatePanel Ajax

Sometimes we have to use the Response.Redirect function in a UpdatePanel... But in most cases this function give an error. Usually, it's 'cause a bit of configuration is missing, in web.config
So, if we add

<httpModules>

<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>

</httpModules>


all works fine.

Friday, December 5, 2008

Pruning "Trash" and "Spam" folders automatically on MDaemon

The accountpruner is a powerful tool, but it’s not always the easiest thing to use. With that in mind, here are some rules from my \MDaemon\App\midnight.bat file that might be useful. This batch file is executed by MDaemon at midnight each night. (If you haven't this file, you can create it and it works).

c:\MDaemon\App\AccountPrune.exe /m /d=10 /p=”Spam.IMAP”
c:\MDaemon\App\AccountPrune.exe /m /d=10 /p=”Junk Mail.IMAP”
c:\MDaemon\App\AccountPrune.exe /m /d=10 /p=”Junk E-mail.IMAP”
c:\MDaemon\App\AccountPrune.exe /m /d=2 /p=”Trash.IMAP”
c:\MDaemon\App\AccountPrune.exe /m /d=2 /p=”Deleted Items.IMAP”
c:\MDaemon\App\AccountPrune.exe /m /d=2 /p=”Deleted Messages.IMAP”


Obviously, if you have installed MDaemon server in an another path, just use it.

The result is that at midnight each night, MDaemon’s accountpruner will go through each user’s mailbox, and in each of the “Spam”, “Junk Mail” and “Junk E-Mail” folders, delete all messages over 10 days old.

In the “Trash”, “Deleted Items” and “Deleted Messages” folders, messages over 2 days old will be deleted. Combine this with the accountpruner’s own options to delete IMAP mail flagged as deleted, and you’ll have a solution that works for users of all mail clients, whether the mail client uses a dedicated “Trash” folder, uses IMAP deleted flag, or both.

Thursday, December 4, 2008

VmWare ESX with Windows based NAS (NTFS)

Above there is the complete procedure to use a Windows Based NAS NTFS share as NFS for VMware ESX server.

The main steps in this process are:

  1. Installing Windows Services for UNIX (WSFU)

  2. Copying the ESX Server password and group files to Windows

  3. Configuring WSFU for accepting ESX Server connections

  4. Sharing the Windows folder for NFS compatibility

  5. Configuring the ESX Server to mount the Window NFS Share as Datastore.



1. Installing Windows Services for UNIX (WSFU)

Download windows services for UNIX at:
http://www.microsoft.com/windowsserversystem/sfu/downloads/default.mspx

Install WSFU on the desired machine
Add in the following options
NFS + Server for NFS
Authentication tools for NFS + user name mapping
After installation, open services control panel applet and change the service ‘User Name Mapping’ to startup automatically and then start the service (if it's not started)


2. Copy the ESX Server password and group files to Windows

Use a program like WinSCP or similar process to copy the following files to your local system where WSFU is installed
You can get WinSCP from the fowling location.
http://winscp.net/eng/download.php#download2
Transfer the file /ect/password and the file /ect/group to C:\SFU or to the location where you installed WSFU


3. Configure WSFU to accepting ESX Server connections

Click Start, Programs, Windows Services for UNIX, Services for UNIX Administration
Go to user name mappings then configuration
Click password and group files
Then browse for the password and group files that you copied, from the browse dialog box for both the password and group fields
Click apply
Then go to maps
Click Show User Maps
List Windows users and list Unix users
Then select a local administrator user on the left that will be mapped to the root account and the root user on the right.
Then click on Add button
Then click apply (upper right)



4. Sharing the Windows folder for NFS compatibility

Right click the local folder you wish to share via NFS
Share the folder by clicking NFS sharing
Type in the name for the share i.e. NFS-VMFS01
Remove allow anonymous access
Click permissions
Now Change type of access to “Read+Write” then check allow root access.


5. Configure the ESX Server to mount the Window NFS Share as VMFS

Open the VC client and highlight the Vi3 host
In the Configure tab choose Networking
Add networking, VMKernel then pick a vSwitch, then give the VMkernel an IP that is accessible via the NFS host.
Now open the storage option for this host
Click add storage, > Network File System
In the Server Field enter in the name or the ip address of your server
In the Folder field enter /NFS-VMFS01 (or the name you give to the share)
For the Datastore I also used NFS-VMFS01

Saturday, November 8, 2008

Add users to Team Foundation Server

All Team Foundation Server editions require users to be members of a Team Foundation Server group at the project level or server level. The level and group depend on the functionality that you want to enable for the user. For example, if you want to have a user create a team project, the user must have the Create New Projects permission set to Allow, must be assigned to the role of Content Manager in SQL Server Reporting Services, and must be assigned to the role of Administrator for Windows SharePoint Services. However, the user does not have to be a member of the local administrator group on the computer. For more information about users and roles, see the topic “Team Foundation Server Permissions” in the Team Foundation Server Administrator’s Guide on MSDN Library.

To add users to Team Foundation Server:

  1. Log on as a Team Foundation Administrator, open Team Explorer, and connect to the Team Foundation Server for which you are adding a user.

  2. From the Team menu, click Team Foundation Server Settings, and then click Group Membership.

  3. In the Global Groups dialog box, click Team Foundation Licensed Users and then click Properties.

  4. In the Team Foundation Server Group properties dialog box, click Windows User or Group, and then click Add.

  5. In the Select Users or Groups dialog box, type the user accounts you want to add, and then click Add.

  6. Click Close.

Note
You cannot use the Global Security group dialog box to add users to this group.
You can add individual user accounts but not a group account.

In this way the user can only connect to the server but can't create or access projects. To complete the configuration, you can use the TFS Admin Tool. It allows a TFS administrator to quickly add users to all three platforms utilized by Team Foundation Server (Team Foundation Server, Sharepoint and SQL Reporting Services) all through one common interface. The tool also allows administrators to change the current permissions on any of the three tiers, identify any errors and view all of the users and their permission sets across Team Foundation Server, Sharepoint, and SQL Reporting Services.

The program is written in C# and is released via CodePlex.

Tuesday, November 4, 2008

Asterisk / Trixbox: listen to calls in progress

With Asterisk or Trixbox it's possible to listen to calls in progress made by other clients.

Insert the line below into "extensions.conf" inside a customized context. In Trixbox or @home write it into "extensions_custom.conf "under [from-internal-custom]

for example:

exten => _61XXX,1,ChanSpy(SIP/${EXTEN:2},q)

with as many X as number of figures or chars in "names" of your extensions (3 in this exemple)

After a reload, is sufficent to type on telephon keypad 61206 to listen the extension 206 call

Asterisk / Trixbox: recording calls

With Asterisk or Trixbox its possible to record clients made calls.
To do it we have to insert the rows below into "extesion.conf" on Asterisk or into "exstension_custom.conf" on Trixbox. (PS: on Trixbox it's also possible to enable this function from the GUI)

exten => _61XXX,1,Monitor(wav,rec${EXTEN:2},m)
exten => _61XXX,2,ChanSpy(SIP/${EXTEN:2},q)
exten => _61XXX,3,Hangup

in /var/spool/asterisk/monitor we'll find the recordings in wav format, named rec"extensionNumber"

Thursday, October 16, 2008

Select Distinct on DataSet with Vb.Net

Functions below allow to do a "Select Distinct" query over a DataSet.

FieldNames is a string array with the name of field for the select distinct input.



Public Function SelectDistinct(ByVal SourceTable As DataTable, _
    ByVal ParamArray FieldNames() As String) As DataTable

    Dim lastValues() As Object
    Dim newTable As DataTable

    If FieldNames Is Nothing OrElse FieldNames.Length = 0 Then
        Throw New ArgumentNullException("FieldNames")
    End If

    lastValues = New Object(FieldNames.Length - 1) {}
    newTable = New DataTable

    For Each field As String In FieldNames
        newTable.Columns.Add(field, SourceTable.Columns(field).DataType)
    Next

    For Each Row As DataRow In SourceTable.Select("", String.Join(", ", FieldNames))
        If Not fieldValuesAreEqual(lastValues, Row, FieldNames) Then
            newTable.Rows.Add(createRowClone(Row, newTable.NewRow(), FieldNames))
            setLastValues(lastValues, Row, FieldNames)
        End If
    Next

    Return newTable
End Function



Private Function fieldValuesAreEqual(ByVal lastValues() As Object, _
    ByVal currentRow As DataRow, ByVal fieldNames() As String) As Boolean

    Dim areEqual As Boolean = True

    For i As Integer = 0 To fieldNames.Length - 1
        If lastValues(i) Is Nothing OrElse Not lastValues(i).Equals(currentRow(fieldNames(i))) Then
            areEqual = False
            Exit For
        End If
    Next

    Return areEqual
End Function



Private Function createRowClone(ByVal sourceRow As DataRow, _
    ByVal newRow As DataRow, ByVal fieldNames() As String) As DataRow

    For Each field As String In fieldNames
        newRow(field) = sourceRow(field)
    Next

    Return newRow
End Function



Private Shared Sub setLastValues(ByVal lastValues() As Object, _
    ByVal sourceRow As DataRow, ByVal fieldNames() As String)

    For i As Integer = 0 To fieldNames.Length - 1
        lastValues(i) = sourceRow(fieldNames(i))
    Next
End Sub

Friday, September 26, 2008

Unzipping a zip file with subfolder with SharpZipLib and VB.net

Unzipping routine using ICSharpCode (IC#Code) released open source dll, called SharpZipLib (#ZipLib), downloadable here


Imports ICSharpCode.SharpZipLib.Zip
......
If File.Exists(fileName) Then

    destPath = fileName.Substring(0, fileName.Length - 4)

    If Not Directory.Exists(destPath) Then
        Directory.CreateDirectory(destPath)
    Else
        For Each s As String In Directory.GetFiles(destPath)
            File.Delete(s)
        Next
    End If

    Dim inStream As New ZipInputStream(File.OpenRead(fileName))
    Dim outStream As FileStream
    Dim entry As ZipEntry
    Dim buff(2047) As Byte
    Dim bytes As Integer

    Do While True
        Try
            entry = inStream.GetNextEntry()
            If entry Is Nothing Then
                Exit Do
            End If

            If entry.Name.Last() = "/" Then
                Directory.CreateDirectory(destPath & "\" & _
                entry.Name.Replace("/", "\"))
            Else
                Try
                    outStream = File.Create(destPath & _
                    "\" & entry.Name, 2048)
                    Do While True
                        bytes = inStream.Read(buff, 0, 2048)
                        If bytes = 0 Then
                            Exit Do
                        End If
                        outStream.Write(buff, 0, bytes)
                    Loop
                    outStream.Close()
                Catch
                End Try
            End If
        Catch
ex As ZipException
            rtn += ex.Message & vbCrLf
        End Try
    Loop

    inStream.Close()
Else
    rtn = "File '" & fileName & "' not found."
End If

Thursday, September 18, 2008

Recursive copy of Files and Folders with VB.Net

It seems so banal, but sometimes the copy of files and folders conteined into a folder can undermine a developer, maybe for its banality.
For this reason, here you have an example of recoursive copy of files and folders.

Private Sub Copy(ByVal SourcePath As String, _
            ByVal DestinationPath As String)
    Dim Files() As String

    If DestinationPath.Chars(DestinationPath.Length - 1) <>
            Path.DirectorySeparatorChar Then
        DestinationPath += Path.DirectorySeparatorChar
    End If

    If Not Directory.Exists(DestinationPath) Then
        Directory.CreateDirectory(DestinationPath)
    End If

    Files = Directory.GetFileSystemEntries(SourcePath)

    Dim Element As String

    For Each Element In Files
        'Sub folders
        If Directory.Exists(Element) Then
            Copy(Element, DestinationPath +
                Path.GetFileName(Element))
            ' File in folder
        Else
            File.Copy(Element, DestinationPath +
                Path.GetFileName(Element), True)
        End If
    Next Element
End Sub

Tuesday, August 26, 2008

Assign a variable from a Select result with SQL Server

Sometimes will be useful saving a Select query result in a variable, perhaps to reuse it inside another query.
The command to do that is very simple:

DECLARE @variable AS datatype

SELECT @variable = Filed FROM Table WHERE Condition

We only have to comply with certain conditions:
  • datatype must be of the same datatype of Field
  • if the query return more than 1 row, the variable contains the last row value
  • is not possible to use TOP clause

Update from Select with SQLServer

Suppose to be in this situation: we have to update some database records starting from query result. There are 2 solutions: we can manual update datas (it will be a problem with thousands of records) or we can use a T-Sql script to do exatcly what we want. Then only condition is that the starting query must have a field on wich we can make a join on.
The script code is below:

UPDATE T
    SET T.Field1a = Q.Field2a,
    T.Fieldb = Q.Field2b
FROM
    (SELECT FieldID, Field2a, Field2b
    FROM Table WHERE Condition) Q
INNER JOIN TableToUpdate T
    ON T.FieldID = Q.FieldID


Where T is the "Table-To-Update" alias and Q is the Select query alias.
The Join clause do the update exactly like we do an "Update ... Where".

Thursday, August 14, 2008

TrixBox Backup

Mondoarchive is a backup solution for *nix systems. It creates .iso files with cd or dvd sizes containing the entire image of disk (like ghost for Windows). It's an extremely powerful solution 'cause, when burned, images are bootable and autorestoring. In this way it's possible to recover the system installation without the reinstallation of all sofware and drivers, for example in case of disk crash.
Moreover, the startup/config script allow to choose where to create image files: on disk, on usb devices, on samba/nfs shares or on ftp.
For any other information, please visit developers site: http://www.mondorescue.org/
The procedure below is optimized for backupping Trixbox versions 2.4 and 2.6 and Asterisk-based systems.

Installation
As root user, do:
cd ~
wget http://www.dbtek.it/Repository/install-mondo.tgz
(or from http://www.astusers.org/install-mondo.tgz)
tar -xzvf install-mondo.tgz
chmod +x install-mondo.sh
./install-mondo.sh

This script downloads all dependencies, install mondo backup program and create a custom configuration for trixbox.
At the installation end, it's necessary to reboot the system.

Next we have to edit the /etc/cron.weekly/mondobackup.cron file to activate the desired backup options and to configure the program. Every instruction needed are written directly into this config file.

To test if the procedure is working as we want: /etc/cron.weekly/mondobackup.cron

WARNING: if there are errors on mounting samba file systems (Netowrk Sharing on Microsoft OS) and yours username or password used for accessing shares contains symbols you must write a ' before and after it.


Restore a backup
To restore a backup we can choose from diffrent ways:

Nuke (formats the destination disk and automatically restores all)
Interactive
Expert

It's also possible to try to restore only the bootloader (if the disk didn't crash):
• Boot from backup CD/DVD and choose Expert Mode
• Type: mondorestore --mbr
• Choose option 28 and then
bash# mount-me
bash# chroot /mnt/RESTORING
bash# lilo or grub-install ’(hd0)’
bash# exit
bash# unmount-me

Nuke Restore
As said, this option completely overwrites the system hard disk, automatically restoring the backup

• Boot from first backsup CD/DVD
• Choose RESTORE
• When asked, insert next CD/DVD (if exists)
• Check for errors

If there are errors, check /tmp/mondorestore.log file.

If you wanna see what the program is doing, press + to analyse the log file “on-the-fly”.

Interactive Restore
The Interactive Mode allow to restore a subset of files from backup or we can use it to restore all files without formatting hard drive.

The interactive restore give the “Editing mountlist screen” that allow to set diffrent sidk geometries. To move through the partitions use up and down arrow keys. To move on buttons use left and right arrow keys.

To restore a subset of files, the procedure is:
• Boot from first backup CD/DVD
• Type interactive
• Answer to questions:
Do you want to partition your devices? no
Do you want to format them? no
Do you want to restore everything? no
Do you want to restore something? yes
Which path do you want to restore? /mydata (for example)
Do you want to run LILO to setup your boot sectors? Yes

Expert Restore
To manually restore:
• Boot from first backup CD/DVD
• Type expert
• Type mondorestore

Saturday, July 12, 2008

Error management on ASP.Net pages

How are managed errors ASP.Net pages?

A way is to modify the event "onError", in Global.asax, and make a server transfer to errors-management pages, tipically for error 500 and error 404.
We can also insert here the code to send a mail in case of error.

But the best thing is to create an HttpModule to intercept error events:

C#
public class ErrorModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.Error += new System.EventHandler(context_Error);
    }

    private void context_Error(object sender, System.EventArgs e)
    {
        Exception exception = HttpContext.Current.Server.GetLastError();
    }

    public void Dispose()
    {
    ...
    }
}

VB.Net
Public Class ErrorModule
    Inherits IHttpModule

    Public Sub Init(ByVal context As HttpApplication)
        AddHandler context.Error, AddressOf Me.context_Error
    End Sub

    Private Sub context_Error(ByVal sender As Object, ByVal e As System.EventArgs)
        Dim exception As Exception = HttpContext.Current.Server.GetLastError
    End Sub

    Public Sub Dispose()
        ...
    End Sub
End Class

and then register it in the Web.config:

<system.web>
    <httpModules>
        <add name="ErrorModule" type="ErrorModule" />
    </httpModules>
</system.web>



HttpModules are "the better ways", 'cause permit reusability and its possible to enable or disable them from Web.config without recompile.

Friday, June 20, 2008

String replacement with Tex or nText fields

Problem: How can I replace a string with another one in a field of Text or nText datatype?

Considerations: If the field was of VarChar or nVarChar type, there is no problem, 'cause in SqlServer exists a function (like in T-Sql) that do it in native mode: the "Replace" function. But this function doesn't work on Text and nText fields. So, we have to use a script builded with another function: UpdateText

Solution:
declare @OldText varchar(1000)
set @OltText= 'Old'

declare curs cursor local fast_forward
for
select
    rowid,
    textptr(Field),
    charindex(@OldText, Field)-1
from
    Table
where
    Field
like
    '%' + @OldText +'%'


declare @NewText varchar(1000)
set @NewText= 'New'

declare @txtlen int
set @txtlen = len(@OldText)


declare @ptr binary(16)
declare @pos int
declare @id int


open curs

fetch next from curs into @id, @ptr, @pos

while @@fetch_status = 0
begin
    updatetext Table.Field @ptr @pos @txtlen @NewText

    fetch next from curs into @id, @ptr, @pos
end

close curs
deallocate curs

Notes:
Table is the reference table
Field is the field where the text will be replaced
rowid is the table id (in this example it's of int type, so the @id variable are set like int, for other datatypes change the declaration of @id variable)

Tuesday, June 10, 2008

Database Connection String for Web.Config

Access Database
<connectionstrings>
  <add name="AccessConnectionString"
   connectionString="Provider=Microsoft.Jet.OLEDB.4.0;
   Data Source=|DataDirectory|dbname.mdb"
   providerName="System.Data.OleDb" />
</connectionstrings>


ODBC Database
<connectionstrings>
  <add name="ODBCConnectionString"
   connectionString="DSN=dsnname;Uid=sa;Pwd=pwd;
   providerName="System.Data.Odbc” />
</connectionstrings>


SQLServer database
<connectionstrings>
  <add name="OLEDBConnectionString"
   connectionString="Server=servername;Integrated Security=SSPI;Database=dbname;"
   providerName="System.Data.SqlClient" />
</connectionstrings>


Excel Connection
<connectionstrings>
  <add name="OLEDBConnectionString"
   connectionString="Provider=Microsoft.Jet.OLEDB.4.0;
   Data Source= filename.xls; Extended Properties=Excel 8.0;"; />
</connectionstrings>


.csv file Connection
<connectionstrings>
  <add name="OLEDBConnectionString"
   connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=filename.csv;
   ExtendedProperties=""Text;HDR=Yes;FMT=Delimited""";/>
</connectionstrings>



Moreover you can use native connection methods for Oracle.

Wednesday, June 4, 2008

Ajax - Response.Write with UpdatePanel

Usually, the Response.Write() method inside an UpdatePanel doesn't work.
To solve this problem, a workaround is to insert a LinkButton out of the UpdatePanel and to associate this control with the postback generated from the object inside the panel.


HTML
<asp:UpdatePanel ID="upd" runat="server">
    …
    <asp:Button runat="server" ID="BUTTON" Text="Click" />
    …
    </asp:UpdatePanel>
<asp:LinkButton ID="ALinkButton" runat="server"></asp:LinkButton>



CODE
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    …
    AddHandler Me.ALinkButton.Click, AddressOf FUNCTION
    Me.BUTTON.Attributes.Add("onclick", Page.ClientScript.GetPostBackEventReference(Me.ALinkButton, ""))

    If Not Page.IsPostBack Then
        …
    End If
    …
End Sub

Protected Sub FUNCTION(ByVal sender As Object, ByVal e As System.EventArgs)
    …
    Response.Write("Text")
    …
End Sub

Tuesday, May 27, 2008

GUID Validator

Working with Unique Identifier (known also as GUID) I need to know if a funtion gived or returned string is really a GUID or something else. Since there isn't a predefined funtion to do that, I create my own function using Regular Expressions:


Public Function IsGUID(ByVal guid As String) As Boolean
    Dim rtn As Boolean = False
    If Not String.IsNullOrEmpty(guid) Then
        Dim guidRegEx As Regex = New Regex("^(\{{0,1}" & _
           "([0-9a-fA-F]){8}-([0-9a-fA-F])" & _
           "{4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-" & _
           "([0-9a-fA-F]){12}\}{0,1})$")
        rtn = guidRegEx.IsMatch(guid)
    Else
        rtn = False
    End If

    Return rtn
End Function

Word 2007 OOXML Tags

Developing a program, you may need to save datas in different formats, like excel or word...
Saving text in word format it's quite simple, but do it in word 2007 format (.docx) it's different (it uses xml). Formatting this text is more difficult, 'cause format tags isn't well documented. This is why i put some of them above.

<p>text</p>
<w:p><w:r><w:t>TEXT</w:t></w:r></w:p>

<br />TEXT
</w:t></w:r><w:br /><w:r><w:t>TEXT

Bold
<w:r><w:rPr><w:b /></rPr>TEXT</w:r>

Underline
<w:r><w:rPr><w:u w:val="single"/></rPr>TEXT</w:r>

Italic
<w:r><w:rPr><w:i /></rPr>TEXT</w:r>

Colors
<w:r><w:rPr><w:color w:val="FF0000" /></rPr>TEXT</w:r>

Sunday, May 18, 2008

Unlocking locked files on Team Foundation Server

Some time ago, working on Team Foundation Server 2005, I have to unlock a number of files locked by other users (for example, files locked in an unavailable Work Area). After some search in Microsoft Newsgroups and in technical documents, i can build a working procedure to unlock them:

1. On command prompt, go to C:\Program Files\Microsoft Visual Studio 8\Common7\IDE on TFS server

2. Write:
“tf lock $/ProjectName/LockedFileName /lock:none /workspace:WorkArea;UserThatLocks /server:TFSServerName

4. Write:
“tf undo $/ProjectName/LockedFileName /workspace:WorkArea;UserThatLocks /server:TFSServerName

Friday, May 16, 2008

Ajax - FadeIn and FadeOut Animation

With Microsoft AjaxToolkit you can do a lot oh things but the most complex (for me) is to apply an animation to an object. However, with a small amount of lines, you can create simple animations and effects for a WebForm.

In this example, we wanna show a customized tooltip when the mouse is over a button and then that it disappears when the mouse is out. We use fadeIn and fadeOut animations, 0.5 seconds long and with a framerate of 20fps:


<cc1:AnimationExtender ID="AnimationExtender1" runat="server"
TargetControlID="ImageButton1">
     <Animations>
          <OnMouseOver>
               <sequence>
                    <StyleAction AnimationTarget="info"
                    Attribute="display" Value="block"/>
                    <FadeIn AnimationTarget="info" Duration=".5"
                    Fps="20" />
               </sequence>
          </OnMouseOver>
          <OnMouseOut>
               <sequence>
                    <FadeOut AnimationTarget="info" Duration=".5"
                    Fps="20" />
                    <StyleAction AnimationTarget="info"
                    Attribute="display" Value="none"/>
               </sequence>
          </OnMouseOut>
     </Animations>
</cc1:AnimationExtender>



info is a "div" that contains our tooltip. Must be written in this way:

<div id="info" style="display: none; z-index: 2; opacity: 0;">

Thursday, May 15, 2008

OpenVPN on PFSense: Site to Site

Assume this scenario:

Office1 LAN: 192.168.0.0/24
Office2 LAN: 192.168.1.0/24

We have to configure the PFSense server to connect this two networks.
One office will be the VPN server, the other will be the VPN client

NB: if you also have a VPN access for road warriors configured, don't change the existing configuration but add a new tunnel.

Office1 configuration
Let's configure Office1 as server.
From “VPN à OpenVPN” menu, select “Server” tab and click on “+”.

Use TCP protocole and, if you have other VPN tunnels, set a diffrent port (in this example i use the port 1193). Obviously we have to creat a firewall rule to permit WAN connection on this port.

“Address pool” must be an independent subnetwork, diffrent from both subnetwork in Office1 and Office2.

In “Remote network” area set the subnet of Office2.

Now we have to generate the “Shared key”. Log into the PfSense server of Office1 via SSH, type “8” (shell) and then use this command:

# openvpn --genkey --secret shared.key

This command creates a new shared key for this OpenVPN server. Then copy the content of shared.key file into the Shared Key WebInterface box and press “Save”.

We have to copy this shared key to use it later on the Office2 server.


Office2 configuration

Let's configure Office2 as client.

From “VPN à OpenVPN” menu, select the “Client” tab and click on “+”.

Use the “TCP” protocol.

“Server address” must be the public IP of Office1.

“Server port” is the connection port for the VPN set on the Office1 PfSense (in this example 1193.)

“Interface IP” must be the IP address of local LAN.

“Remote network” must be the IP address of the Office1 LAN dell’Ufficio1.

Paste the previous generated shared key into the shared key box and then click on “Save”.

Now the VPN tunnel between this two offices should be “up and running”.