diff --git a/app/modules/ws2p/lib/ws2p-upnp.ts b/app/modules/upnp-provider.ts
similarity index 80%
rename from app/modules/ws2p/lib/ws2p-upnp.ts
rename to app/modules/upnp-provider.ts
index 3b2140de831767046f687f7f9a5284bc1dea192e..cc7a396f936131eccce7fd49a2dcc1a549ca97c1 100644
--- a/app/modules/ws2p/lib/ws2p-upnp.ts
+++ b/app/modules/upnp-provider.ts
@@ -11,9 +11,6 @@
 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 // GNU Affero General Public License for more details.
 
-import {WS2PConstants} from "./constants"
-import {ConfDTO} from "../../../lib/dto/ConfDTO"
-
 const upnp = require('nat-upnp');
 
 export interface UPnPBinding {
@@ -22,13 +19,20 @@ export interface UPnPBinding {
   port:number
 }
 
-export class WS2PUpnp {
+export class UpnpProvider {
 
   private currentConfig:UPnPBinding|null
   private interval:NodeJS.Timer|null
   private client = upnp.createClient()
 
-  constructor(private logger:any, private conf:ConfDTO) {}
+  constructor(
+    private portStart: number,
+    private portEnd: number,
+    private identifier: string,
+    private upnpInterval = 300,
+    private ttl = 600,
+    private logger?:any,
+  ) {}
 
   async checkUPnPisAvailable() {
     try {
@@ -52,9 +56,7 @@ export class WS2PUpnp {
   }
 
   getUpnpDescription() {
-    const uuid = (this.conf.ws2p && this.conf.ws2p.uuid) || "no-uuid-yet"
-    const suffix = this.conf.pair.pub.substr(0, 6) + ":" + uuid
-    return 'duniter:ws2p:' + suffix
+    return 'duniter:' + this.identifier
   }
 
   /**
@@ -66,17 +68,17 @@ export class WS2PUpnp {
       if (!this.currentConfig) {
         this.currentConfig = await this.getAvailablePort(this.client)
       }
-      this.logger.trace('WS2P: mapping external port %s to local %s using UPnP...', this.currentConfig.port, [this.currentConfig.host, this.currentConfig.port].join(':'))
+      this.logger && this.logger.trace('WS2P: mapping external port %s to local %s using UPnP...', this.currentConfig.port, [this.currentConfig.host, this.currentConfig.port].join(':'))
       const client = upnp.createClient()
       client.portMapping({
         'public': this.currentConfig.port,
         'private': this.currentConfig.port,
-        'ttl': WS2PConstants.WS2P_UPNP_TTL,
+        'ttl': this.ttl,
         'description': this.getUpnpDescription()
       }, (err:any) => {
         client.close()
         if (err) {
-          this.logger.warn(err)
+          this.logger && this.logger.warn(err)
           return reject(err)
         }
         resolve(this.currentConfig)
@@ -89,7 +91,7 @@ export class WS2PUpnp {
     const available = await this.checkUPnPisAvailable()
     if (available) {
       // Update UPnP IGD every INTERVAL seconds
-      this.interval = setInterval(() => this.openPort(), 1000 * WS2PConstants.WS2P_UPNP_INTERVAL)
+      this.interval = setInterval(() => this.openPort(), 1000 * this.upnpInterval)
       const { host, port } = await this.openPort()
       return { host, port, available }
     }
@@ -121,8 +123,8 @@ export class WS2PUpnp {
   }
 
   private async getAvailablePort(client:any) {
-    const localIP = await WS2PUpnp.getLocalIP(client)
-    const remoteIP = await WS2PUpnp.getRemoteIP(client)
+    const localIP = await UpnpProvider.getLocalIP(client)
+    const remoteIP = await UpnpProvider.getRemoteIP(client)
     const mappings:{
       private: {
         host:string
@@ -131,15 +133,15 @@ export class WS2PUpnp {
         port:number
       }
       description:string
-    }[] = await WS2PUpnp.getUPnPMappings(client)
+    }[] = await UpnpProvider.getUPnPMappings(client)
     const thisDesc = this.getUpnpDescription()
     const externalPortsUsed = mappings.filter((m) => m.description !== thisDesc).map((m) => m.public.port)
-    let availablePort = WS2PConstants.WS2P_PORTS_START
+    let availablePort = this.portStart
     while (externalPortsUsed.indexOf(availablePort) !== -1
-      && availablePort <= WS2PConstants.WS2P_PORTS_END) {
+      && availablePort <= this.portEnd) {
       availablePort++
     }
-    if (availablePort > WS2PConstants.WS2P_PORTS_END) {
+    if (availablePort > this.portEnd) {
       throw "No port available for UPnP"
     }
     return {
diff --git a/app/modules/ws2p/index.ts b/app/modules/ws2p/index.ts
index 6eac3d27dd2230be304eaf521d796e7bb790014d..8deb5523c8d8127f66765245dfad7e68dc014ba9 100644
--- a/app/modules/ws2p/index.ts
+++ b/app/modules/ws2p/index.ts
@@ -16,9 +16,9 @@ import {ConfDTO, WS2PConfDTO} from "../../lib/dto/ConfDTO"
 import {Server} from "../../../server"
 import * as stream from 'stream';
 import {WS2PCluster} from "./lib/WS2PCluster"
-import {WS2PUpnp} from "./lib/ws2p-upnp"
 import {CommonConstants} from "../../lib/common-libs/constants"
 import {NewLogger} from "../../lib/logger"
+import {UpnpProvider} from "../upnp-provider"
 
 const constants = require("../../lib/constants");
 const logger = NewLogger()
@@ -196,7 +196,7 @@ export class WS2PAPI extends stream.Transform {
 
   // Public http interface
   private cluster:WS2PCluster
-  private upnpAPI:WS2PUpnp|null
+  private upnpAPI:UpnpProvider|null
 
   constructor(
     private server:Server,
@@ -235,7 +235,15 @@ export class WS2PAPI extends stream.Transform {
           this.upnpAPI.stopRegular();
         }
         try {
-          this.upnpAPI = new WS2PUpnp(logger, this.conf)
+          const uuid = (this.conf.ws2p && this.conf.ws2p.uuid) || "no-uuid-yet"
+          const suffix = this.conf.pair.pub.substr(0, 6) + ":" + uuid
+          this.upnpAPI = new UpnpProvider(
+            WS2PConstants.WS2P_PORTS_START,
+            WS2PConstants.WS2P_PORTS_END,
+            ':ws2p:' + suffix,
+            WS2PConstants.WS2P_UPNP_INTERVAL,
+            WS2PConstants.WS2P_UPNP_TTL,
+            logger)
           const { host, port, available } = await this.upnpAPI.startRegular()
           if (available) {
             // Defaults UPnP to true if not defined and available