2 * Get External IP address by STUN protocol
4 * Based on project Minimalistic STUN client "ministun"
5 * https://code.google.com/p/ministun/
7 * This program is free software, distributed under the terms of
8 * the GNU General Public License Version 2. See the LICENSE file
9 * at the top of the source tree.
11 * STUN is described in RFC3489 and it is based on the exchange
12 * of UDP packets between a client and one or more servers to
13 * determine the externally visible address (and port) of the client
14 * once it has gone through the NAT boxes that connect it to the
16 * The simplest request packet is just the header defined in
17 * struct stun_header, and from the response we may just look at
18 * one attribute, STUN_MAPPED_ADDRESS, that we find in the response.
19 * By doing more transactions with different server addresses we
20 * may determine more about the behaviour of the NAT boxes, of
21 * course - the details are in the RFC.
23 * All STUN packets start with a simple header made of a type,
24 * length (excluding the header) and a 16-byte random transaction id.
25 * Following the header we may have zero or more attributes, each
26 * structured as a type, length and a value (whose format depends
27 * on the type, but often contains addresses).
28 * Of course all fields are in network format.
36 #include <sys/types.h>
40 #include <sys/socket.h>
41 #include <netinet/in.h>
42 #include <arpa/inet.h>
54 extern int GetRandInt(int nMax);
55 extern uint64_t GetRand(uint64_t nMax);
57 /*---------------------------------------------------------------------*/
64 /*---------------------------------------------------------------------*/
65 static const int StunSrvListQty = 701; // Must be PRIME!!!!!
67 static struct StunSrv StunSrvList[701] = {
68 {"iphone-stun.strato-iphone.de", 3478},
69 {"stun.1-voip.com", 3478},
70 {"stun.12connect.com", 3478},
71 {"stun.12voip.com", 3478},
72 {"stun.1531.ru", 3478},
73 {"stun.1cbit.ru", 3478},
74 {"stun.1und1.de", 3478},
75 {"stun.3clogic.com", 3478},
76 {"stun.3cx.com", 3478},
77 {"stun.3deluxe.de", 3478},
78 {"stun.3wayint.com", 3478},
79 {"stun.5sn.com", 3478},
80 {"stun.a-mm.tv", 3478},
81 {"stun.aa.net.uk", 3478},
82 {"stun.aaisp.co.uk", 3478},
83 {"stun.ab-hamm.de", 3478},
84 {"stun.aceweb.com", 3478},
85 {"stun.acquageraci.it", 3478},
86 {"stun.acrobits.cz", 3478},
87 {"stun.acronis.com", 3478},
88 {"stun.actionvoip.com", 3478},
89 {"stun.adafrance.ru", 3478},
90 {"stun.advfn.com", 3478},
91 {"stun.aeta-audio.com", 3478},
92 {"stun.aeta.com", 3478},
93 {"stun.alberon.cz", 3478},
94 {"stun.alexeev.in.ua", 3478},
95 {"stun.allflac.com", 3478},
96 {"stun.alphacron.de", 3478},
97 {"stun.alpirsbacher.de", 3478},
98 {"stun.amiwx.com", 3478},
99 {"stun.anglodance.co.uk", 3478},
100 {"stun.anlx.net", 3478},
101 {"stun.ansur.no", 3478},
102 {"stun.antisip.com", 3478},
103 {"stun.arkh-edu.ru", 3478},
104 {"stun.artrage.com", 3478},
105 {"stun.atagverwarming.nl", 3478},
106 {"stun.atmapro.ru", 3478},
107 {"stun.autosystem.com", 3478},
108 {"stun.avigora.com", 3478},
109 {"stun.avigora.fr", 3478},
110 {"stun.avoxi.com", 3478},
111 {"stun.axeos.nl", 3478},
112 {"stun.axialys.net", 3478},
113 {"stun.azurecoast.com", 3478},
114 {"stun.b2b2c.ca", 3478},
115 {"stun.babelforce.com", 3478},
116 {"stun.bahnhof.net", 3478},
117 {"stun.baileymarine.co.uk", 3478},
118 {"stun.baltmannsweiler.de", 3478},
119 {"stun.bandyer.com", 3478},
120 {"stun.barbaratabita.it", 3478},
121 {"stun.bau-ha.us", 3478},
122 {"stun.bearstech.com", 3478},
123 {"stun.beckhallmalham.com", 3478},
124 {"stun.beebeetle.com", 3478},
125 {"stun.bekkurso.info", 3478},
126 {"stun.bergophor.de", 3478},
127 {"stun.bernardoprovenzano.net", 3478},
128 {"stun.bernies-bergwelt.com", 3478},
129 {"stun.bethesda.net", 3478},
130 {"stun.biamp.com", 3478},
131 {"stun.bimp.fr", 3478},
132 {"stun.bistri.com", 3478},
133 {"stun.bitburger.de", 3478},
134 {"stun.bluesip.net", 3478},
135 {"stun.bolignet.dk", 3478},
136 {"stun.bomgar.com", 3478},
137 {"stun.botonakis.com", 3478},
138 {"stun.bridesbay.com", 3478},
139 {"stun.budgetsip.com", 3478},
140 {"stun.bultest.org", 3478},
141 {"stun.bungi.com", 3478},
142 {"stun.business-isp.nl", 3478},
143 {"stun.bytedesk.com", 3478},
144 {"stun.cablenet-as.net", 3478},
145 {"stun.cabsoapp.com", 3478},
146 {"stun.call.me", 3478},
147 {"stun.callromania.ro", 3478},
148 {"stun.callwithus.com", 3478},
149 {"stun.canwe.ca", 3478},
150 {"stun.careerarc.com", 3478},
151 {"stun.carlovizzini.it", 3478},
152 {"stun.cdosea.org", 3478},
153 {"stun.cellmail.com", 3478},
154 {"stun.chaosmos.de", 3478},
155 {"stun.chatous.com", 3478},
156 {"stun.cheapvoip.com", 3478},
157 {"stun.chewinggum.nl", 3478},
158 {"stun.cibercloud.com.br", 3478},
159 {"stun.circledoo.com", 3478},
160 {"stun.cle.com.ua", 3478},
161 {"stun.clickphone.ro", 3478},
162 {"stun.clonesgame.com", 3478},
163 {"stun.cloopen.com", 3478},
164 {"stun.club-galicia-bonn.de", 3478},
165 {"stun.cnj.gov.br", 3478},
166 {"stun.cnj.jus.br", 3478},
167 {"stun.coffee-sen.com", 3478},
168 {"stun.commpeak.com", 3478},
169 {"stun.comrex.com", 3478},
170 {"stun.comtube.com", 3478},
171 {"stun.comtube.ru", 3478},
172 {"stun.connecteddata.com", 3478},
173 {"stun.cope.es", 3478},
174 {"stun.counterpath.com", 3478},
175 {"stun.counterpath.net", 3478},
176 {"stun.cozy.org", 3478},
177 {"stun.createweb.de", 3478},
178 {"stun.crimeastar.net", 3478},
179 {"stun.crononauta.com", 3478},
180 {"stun.cros.net", 3478},
181 {"stun.csforall.org", 3478},
182 {"stun.ctafauni.it", 3478},
183 {"stun.databay.de", 3478},
184 {"stun.davemadethis.com", 3478},
185 {"stun.dcalling.de", 3478},
186 {"stun.deepfinesse.com", 3478},
187 {"stun.degaronline.com", 3478},
188 {"stun.demos.ru", 3478},
189 {"stun.demos.su", 3478},
190 {"stun.deutscherskiverband.de", 3478},
191 {"stun.diallog.com", 3478},
192 {"stun.dincloud.com", 3478},
193 {"stun.disroot.org", 3478},
194 {"stun.dls.net", 3478},
195 {"stun.dokom.net", 3478},
196 {"stun.dorfbrunnen.eu", 3478},
197 {"stun.dorisgraf.de", 3478},
198 {"stun.dowlatow.ru", 3478},
199 {"stun.draci.info", 3478},
200 {"stun.dreifaltigkeit-stralsund.de", 3478},
201 {"stun.dsin-berufsschulen.de", 3478},
202 {"stun.dsin-blog.de", 3478},
203 {"stun.dukun.de", 3478},
204 {"stun.dumdarac.com", 3478},
205 {"stun.dunyatelekom.com", 3478},
206 {"stun.dus.net", 3478},
207 {"stun.eaclipt.org", 3478},
208 {"stun.easter-eggs.com", 3478},
209 {"stun.easycall.pl", 3478},
210 {"stun.easyvoip.com", 3478},
211 {"stun.edwin-wiegele.at", 3478},
212 {"stun.effexx.com", 3478},
213 {"stun.einfachcallback.de", 3478},
214 {"stun.ekiga.net", 3478},
215 {"stun.ekir.de", 3478},
216 {"stun.eleusi.com", 3478},
217 {"stun.elitetele.com", 3478},
218 {"stun.engineeredarts.co.uk", 3478},
219 {"stun.eol.co.nz", 3478},
220 {"stun.eoni.com", 3478},
221 {"stun.epygi.com", 3478},
222 {"stun.eurescom.de", 3478},
223 {"stun.eurescom.eu", 3478},
224 {"stun.eurosys.be", 3478},
225 {"stun.evolution-movement.com", 3478},
226 {"stun.exoplatform.org", 3478},
227 {"stun.expandable.io", 3478},
228 {"stun.extrasaltmobile.com", 3478},
229 {"stun.ezuce.com", 3478},
230 {"stun.faceflow.com", 3478},
231 {"stun.faelix.net", 3478},
232 {"stun.fairytel.at", 3478},
233 {"stun.faktortel.com.au", 3478},
234 {"stun.fathomvoice.com", 3478},
235 {"stun.fbsbx.com", 3478},
236 {"stun.feuerwehrmuseum.at", 3478},
237 {"stun.fiberpipe.net", 3478},
238 {"stun.files.fm", 3478},
239 {"stun.finbolt.eu", 3478},
240 {"stun.finsterwalder.com", 3478},
241 {"stun.fitauto.ru", 3478},
242 {"stun.fixup.net", 3478},
243 {"stun.fmo.de", 3478},
244 {"stun.foad.me.uk", 3478},
245 {"stun.fondazioneroccochinnici.it", 3478},
246 {"stun.framasoft.org", 3478},
247 {"stun.framatalk.org", 3478},
248 {"stun.francescopaologravina.it", 3478},
249 {"stun.freecall.com", 3478},
250 {"stun.freeswitch.org", 3478},
251 {"stun.freevoipdeal.com", 3478},
252 {"stun.frozenmountain.com", 3478},
253 {"stun.funwithelectronics.com", 3478},
254 {"stun.fusion-lifestyle.eu", 3478},
255 {"stun.futurasp.es", 3478},
256 {"stun.galeriemagnet.at", 3478},
257 {"stun.galerievorspann.com", 3478},
258 {"stun.gap.im", 3478},
259 {"stun.geekyboo.com", 3478},
260 {"stun.geesthacht.de", 3478},
261 {"stun.genymotion.com", 3478},
262 {"stun.geonet.ro", 3478},
263 {"stun.getzoop.com", 3478},
264 {"stun.gezondheid-solidariteit.be", 3478},
265 {"stun.gigaset.net", 3478},
266 {"stun.gkarnet.org", 3478},
267 {"stun.globalmeet.com", 3478},
268 {"stun.gmx.de", 3478},
269 {"stun.gmx.net", 3478},
270 {"stun.gntel.nl", 3478},
271 {"stun.godatenow.com", 3478},
272 {"stun.goldener-internetpreis.de", 3478},
273 {"stun.goldfish.ie", 3478},
274 {"stun.goober.com", 3478},
275 {"stun.gotye.com.cn", 3478},
276 {"stun.graftlab.com", 3478},
277 {"stun.gravitel.ru", 3478},
278 {"stun.grazertrinkwasseringefahr.at", 3478},
279 {"stun.groenewold-newmedia.de", 3478},
280 {"stun.gruene.at", 3478},
281 {"stun.guenzburg.de", 3478},
282 {"stun.gulfsip.com", 3478},
283 {"stun.gurumd.net", 3478},
284 {"stun.h4v.eu", 3478},
285 {"stun.hacknology.de", 3478},
286 {"stun.halonet.pl", 3478},
287 {"stun.hanacke.net", 3478},
288 {"stun.hardt-ware.de", 3478},
289 {"stun.healthtap.com", 3478},
290 {"stun.heeds.eu", 3478},
291 {"stun.hicare.net", 3478},
292 {"stun.hide.me", 3478},
293 {"stun.highfidelity.io", 3478},
294 {"stun.hinet.net", 3478},
295 {"stun.hiphone.org", 3478},
296 {"stun.histocaffe.com", 3478},
297 {"stun.hitv.com", 3478},
298 {"stun.hobby-drechselei.de", 3478},
299 {"stun.hoiio.com", 3478},
300 {"stun.hosteurope.de", 3478},
301 {"stun.hot-chilli.net", 3478},
302 {"stun.hotelparadisebeach.it", 3478},
303 {"stun.ica-net.it", 3478},
304 {"stun.ideasip.com", 3478},
305 {"stun.idnext.net", 3478},
306 {"stun.ihk.cn", 3478},
307 {"stun.imafex.sk", 3478},
308 {"stun.imp.ch", 3478},
309 {"stun.ines-seidel.de", 3478},
310 {"stun.inetvl.ru", 3478},
311 {"stun.infoartikel.site", 3478},
312 {"stun.infra.net", 3478},
313 {"stun.innotel.com.au", 3478},
314 {"stun.innovaphone.com", 3478},
315 {"stun.innovaphone.de", 3478},
316 {"stun.instantteleseminar.com", 3478},
317 {"stun.internetcalls.com", 3478},
318 {"stun.interplanet.it", 3478},
319 {"stun.intervoip.com", 3478},
320 {"stun.invaluable.com", 3478},
321 {"stun.ipex.cz", 3478},
322 {"stun.ippi.com", 3478},
323 {"stun.ippi.fr", 3478},
324 {"stun.irishvoip.com", 3478},
325 {"stun.isp.net.au", 3478},
326 {"stun.issabel.org", 3478},
327 {"stun.istitutogramscisiciliano.it", 3478},
328 {"stun.it-zone.org", 3478},
329 {"stun.it1.hr", 3478},
330 {"stun.ivao.aero", 3478},
331 {"stun.ivao.co.uk", 3478},
332 {"stun.ivi.at", 3478},
333 {"stun.ixc.ua", 3478},
334 {"stun.jabber.dk", 3478},
335 {"stun.jabbim.cz", 3478},
336 {"stun.janmedia.pl", 3478},
337 {"stun.jay.net", 3478},
338 {"stun.jesuislibre.net", 3478},
339 {"stun.jowisoftware.de", 3478},
340 {"stun.jpluso.cz", 3478},
341 {"stun.julienschmidt.com", 3478},
342 {"stun.julosoft.net", 3478},
343 {"stun.jumblo.com", 3478},
344 {"stun.junet.se", 3478},
345 {"stun.justvoip.com", 3478},
346 {"stun.kanatasymphony.ca", 3478},
347 {"stun.kanojo.de", 3478},
348 {"stun.kaospilot.dk", 3478},
349 {"stun.kaospilot.no", 3478},
350 {"stun.kaospilot.se", 3478},
351 {"stun.kaospilots.dk", 3478},
352 {"stun.kaseya.com", 3478},
353 {"stun.katholischekirche-ruegen.de", 3478},
354 {"stun.kaznpu.kz", 3478},
355 {"stun.keatsmuseum.frl", 3478},
356 {"stun.kedr.io", 3478},
357 {"stun.kendama.ru", 3478},
358 {"stun.kiesler.at", 3478},
359 {"stun.kitamaebune.com", 3478},
360 {"stun.klimaschutzgarten.at", 3478},
361 {"stun.ko2100.at", 3478},
362 {"stun.kolatzek.org", 3478},
363 {"stun.komsa.de", 3478},
364 {"stun.kore.com", 3478},
365 {"stun.kostenloses-forum.com", 3478},
366 {"stun.kotter.net", 3478},
367 {"stun.kreis-bergstrasse.de", 3478},
368 {"stun.l.google.com", 19302},
369 {"stun.l.google.com", 19305},
370 {"stun.labs.net", 3478},
371 {"stun.lacompagnieducode.org", 3478},
372 {"stun.ladridiricette.it", 3478},
373 {"stun.landvast.nl", 3478},
374 {"stun.ldiglobal.org", 3478},
375 {"stun.le-space.de", 3478},
376 {"stun.lebendigefluesse.at", 3478},
377 {"stun.leibergmbh.de", 3478},
378 {"stun.leonde.org", 3478},
379 {"stun.lerros.com", 3478},
380 {"stun.leucotron.com.br", 3478},
381 {"stun.levigo.de", 3478},
382 {"stun.lindab.com", 3478},
383 {"stun.lineaencasa.com", 3478},
384 {"stun.linphone.org", 3478},
385 {"stun.linuxtrent.it", 3478},
386 {"stun.liveo.fr", 3478},
387 {"stun.lleida.net", 3478},
388 {"stun.localphone.com", 3478},
389 {"stun.logenex.com", 3478},
390 {"stun.logic.ky", 3478},
391 {"stun.londonweb.net", 3478},
392 {"stun.lovense.com", 3478},
393 {"stun.lowratevoip.com", 3478},
394 {"stun.lundimatin.fr", 3478},
395 {"stun.m-online.net", 3478},
396 {"stun.madavi.de", 3478},
397 {"stun.mage.com.vn", 3478},
398 {"stun.magnocall.com", 3478},
399 {"stun.magyarphone.eu", 3478},
400 {"stun.malemotion.com", 3478},
401 {"stun.mangotele.com", 3478},
402 {"stun.marble.io", 3478},
403 {"stun.marcelproust.it", 3478},
404 {"stun.mda.gov.br", 3478},
405 {"stun.mdaemon.com", 3478},
406 {"stun.medvc.eu", 3478},
407 {"stun.meebl.de", 3478},
408 {"stun.meetangee.com", 3478},
409 {"stun.meetwife.com", 3478},
410 {"stun.megakosmos.com.br", 3478},
411 {"stun.megatel.si", 3478},
412 {"stun.meowsbox.com", 3478},
413 {"stun.millenniumarts.org", 3478},
414 {"stun.mit.de", 3478},
415 {"stun.miwifi.com", 3478},
416 {"stun.mixvoip.com", 3478},
417 {"stun.mls.com.br", 3478},
418 {"stun.mobile-italia.com", 3478},
419 {"stun.modulus.gr", 3478},
420 {"stun.modxclub.ru", 3478},
421 {"stun.mondiaspora.net", 3478},
422 {"stun.mondiaspora.org", 3478},
423 {"stun.moonlight-stream.org", 3478},
424 {"stun.mot-net.com", 3478},
425 {"stun.mrmondialisation.org", 3478},
426 {"stun.muoversi.net", 3478},
427 {"stun.museumsguetesiegel.at", 3478},
428 {"stun.myfreecams.com", 3478},
429 {"stun.myfriends.ru", 3478},
430 {"stun.myhowto.org", 3478},
431 {"stun.mylio.com", 3478},
432 {"stun.myspeciality.com", 3478},
433 {"stun.myvoipapp.com", 3478},
434 {"stun.myvoiptraffic.com", 3478},
435 {"stun.mywatson.it", 3478},
436 {"stun.nabto.com", 3478},
437 {"stun.nanocosmos.de", 3478},
438 {"stun.naturfakta.com", 3478},
439 {"stun.naturfakta.no", 3478},
440 {"stun.nautile.nc", 3478},
441 {"stun.ncic.com", 3478},
442 {"stun.neomedia.it", 3478},
443 {"stun.nerathor.com", 3478},
444 {"stun.net-mag.cz", 3478},
445 {"stun.netappel.com", 3478},
446 {"stun.newrocktech.com", 3478},
447 {"stun.nexphone.ch", 3478},
448 {"stun.next-gen.ro", 3478},
449 {"stun.nextcloud.com", 3478},
450 {"stun.nexxtmobile.de", 3478},
451 {"stun.nfon.net", 3478},
452 {"stun.nicokrause.com", 3478},
453 {"stun.nieuwland.cc", 3478},
454 {"stun.niksteknoloji.com", 3478},
455 {"stun.nonoh.net", 3478},
456 {"stun.nosapps.com", 3478},
457 {"stun.nottingham.ac.uk", 3478},
458 {"stun.nova.is", 3478},
459 {"stun.nstelcom.com", 3478},
460 {"stun.obovsem.com", 3478},
461 {"stun.odr.de", 3478},
462 {"stun.officinabit.com", 3478},
463 {"stun.olimontel.it", 3478},
464 {"stun.omnitor.se", 3478},
465 {"stun.omnivoice.eu", 3478},
466 {"stun.oncloud7.ch", 3478},
467 {"stun.onesuite.com", 3478},
468 {"stun.onez.cn", 3478},
469 {"stun.onthenet.com.au", 3478},
470 {"stun.ooma.com", 3478},
471 {"stun.openjobs.hu", 3478},
472 {"stun.openvoip.it", 3478},
473 {"stun.optdyn.com", 3478},
474 {"stun.orszaczky.com", 3478},
475 {"stun.ortopediacoam.it", 3478},
476 {"stun.osbid.cz", 3478},
477 {"stun.otos.pl", 3478},
478 {"stun.ovesnekladruby.cz", 3478},
479 {"stun.ozekiphone.com", 3478},
480 {"stun.pados.hu", 3478},
481 {"stun.palava.tv", 3478},
482 {"stun.parcodeinebrodi.it", 3478},
483 {"stun.parejas.net", 3478},
484 {"stun.pavelepifanov.org", 3478},
485 {"stun.pawlowicz.name", 3478},
486 {"stun.pbo.ru", 3478},
487 {"stun.peeters.com", 3478},
488 {"stun.peethultra.be", 3478},
489 {"stun.penserpouragir.org", 3478},
490 {"stun.peoplefone.ch", 3478},
491 {"stun.personal-voip.de", 3478},
492 {"stun.phone.com", 3478},
493 {"stun.photojim.ca", 3478},
494 {"stun.phytter.com", 3478},
495 {"stun.piratecinema.org", 3478},
496 {"stun.piratenbrandenburg.de", 3478},
497 {"stun.pjsip.org", 3478},
498 {"stun.planetarium.com.br", 3478},
499 {"stun.plexicomm.net", 3478},
500 {"stun.pobeda-club.ru", 3478},
501 {"stun.poetamatusel.org", 3478},
502 {"stun.poivy.com", 3478},
503 {"stun.potsdamvibes.de", 3478},
504 {"stun.powervoip.com", 3478},
505 {"stun.ppdi.com", 3478},
506 {"stun.provectio.fr", 3478},
507 {"stun.pruefplan.com", 3478},
508 {"stun.psipsi.com.br", 3478},
509 {"stun.pure-ip.com", 3478},
510 {"stun.qbictechnology.com", 3478},
511 {"stun.qcol.net", 3478},
512 {"stun.qq.com", 3478},
513 {"stun.qualitalia.fr", 3478},
514 {"stun.qwant.com", 3478},
515 {"stun.rackco.com", 3478},
516 {"stun.racknine.net", 3478},
517 {"stun.radiojar.com", 3478},
518 {"stun.ransquawk.com", 3478},
519 {"stun.readyforsky.com", 3478},
520 {"stun.realgarant.com", 3478},
521 {"stun.redworks.nl", 3478},
522 {"stun.revreso.de", 3478},
523 {"stun.ridesroadsandronman.com", 3478},
524 {"stun.ringostat.com", 3478},
525 {"stun.ringvoz.com", 3478},
526 {"stun.rmf.pl", 3478},
527 {"stun.roannais-agglomeration.fr", 3478},
528 {"stun.robocup.at", 3478},
529 {"stun.rockenstein.de", 3478},
530 {"stun.rolmail.net", 3478},
531 {"stun.romaaeterna.nl", 3478},
532 {"stun.romancecompass.com", 3478},
533 {"stun.root-1.de", 3478},
534 {"stun.ru-brides.com", 3478},
535 {"stun.rudtp.ru", 3478},
536 {"stun.rynga.com", 3478},
537 {"stun.sacko.com.au", 3478},
538 {"stun.salustelehealth.com", 3478},
539 {"stun.samy.pl", 3478},
540 {"stun.sanierer.at", 3478},
541 {"stun.sante-solidarite.be", 3478},
542 {"stun.saooti.com", 3478},
543 {"stun.saratov-rcdo.ru", 3478},
544 {"stun.saripkro.ru", 3478},
545 {"stun.savemgo.com", 3478},
546 {"stun.scalix.com", 3478},
547 {"stun.schlund.de", 3478},
548 {"stun.schoeffel.de", 3478},
549 {"stun.schulinformatik.at", 3478},
550 {"stun.secret-wg.org", 3478},
551 {"stun.selasky.org", 3478},
552 {"stun.semiocast.com", 3478},
553 {"stun.senstar.com", 3478},
554 {"stun.sewan.fr", 3478},
555 {"stun.sg-slope.com", 3478},
556 {"stun.shadrinsk.net", 3478},
557 {"stun.sharpbai.com", 3478},
558 {"stun.shy.cz", 3478},
559 {"stun.sibel.by", 3478},
560 {"stun.siedle.com", 3478},
561 {"stun.sigmavoip.com", 3478},
562 {"stun.signalwire.com", 3478},
563 {"stun.simlar.org", 3478},
564 {"stun.simplewan.com", 3478},
565 {"stun.sip.us", 3478},
566 {"stun.sipdiscount.com", 3478},
567 {"stun.sipgate.net", 10000},
568 {"stun.sipgate.net", 3478},
569 {"stun.sipglobalphone.com", 3478},
570 {"stun.siplogin.de", 3478},
571 {"stun.sipnet.com", 3478},
572 {"stun.sipnet.net", 3478},
573 {"stun.sipnet.ru", 3478},
574 {"stun.siportal.it", 3478},
575 {"stun.sippeer.dk", 3478},
576 {"stun.sipthor.net", 3478},
577 {"stun.siptraffic.com", 3478},
578 {"stun.siptrunk.com", 3478},
579 {"stun.sipy.cz", 3478},
580 {"stun.sius.com", 3478},
581 {"stun.sketch.io", 3478},
582 {"stun.skrumble.com", 3478},
583 {"stun.sky.od.ua", 3478},
584 {"stun.skydrone.aero", 3478},
585 {"stun.slackline.at", 3478},
586 {"stun.sma.de", 3478},
587 {"stun.smart-university.ru", 3478},
588 {"stun.smartvoip.com", 3478},
589 {"stun.smdr.ru", 3478},
590 {"stun.smsdiscount.com", 3478},
591 {"stun.smslisto.com", 3478},
592 {"stun.snafu.de", 3478},
593 {"stun.soho66.co.uk", 3478},
594 {"stun.soiro.ru", 3478},
595 {"stun.sokoll.com", 3478},
596 {"stun.solcon.nl", 3478},
597 {"stun.solnet.ch", 3478},
598 {"stun.solomo.de", 3478},
599 {"stun.sonetel.com", 3478},
600 {"stun.sonetel.net", 3478},
601 {"stun.sovtest.ru", 3478},
602 {"stun.sparvoip.de", 3478},
603 {"stun.speedy.com.ar", 3478},
604 {"stun.splicecom.com", 3478},
605 {"stun.spoiltheprincess.com", 3478},
606 {"stun.spreed.me", 3478},
607 {"stun.srce.hr", 3478},
608 {"stun.stadtwerke-eutin.de", 3478},
609 {"stun.stbuehler.de", 3478},
610 {"stun.steinbeis-smi.de", 3478},
611 {"stun.stochastix.de", 3478},
612 {"stun.stratusvideo.com", 3478},
613 {"stun.streamix.live", 3478},
614 {"stun.streamnow.ch", 3478},
615 {"stun.studio-link.de", 3478},
616 {"stun.studio71.it", 3478},
617 {"stun.stunprotocol.org", 3478},
618 {"stun.stuttgart-ix.de", 3478},
619 {"stun.surjaring.it", 3478},
620 {"stun.surrealnetworks.com", 3478},
621 {"stun.swissquote.com", 3478},
622 {"stun.swrag.de", 3478},
623 {"stun.sylaps.com", 3478},
624 {"stun.symonics.com", 3478},
625 {"stun.syncthing.net", 3478},
626 {"stun.synergiejobs.be", 3478},
627 {"stun.syrex.co.za", 3478},
628 {"stun.szatmarnet.hu", 3478},
629 {"stun.t-online.de", 3478},
630 {"stun.talk.by", 3478},
631 {"stun.talkfusionconnect.com", 3478},
632 {"stun.talkho.com", 3478},
633 {"stun.talking-forex.com", 3478},
634 {"stun.talks.by", 3478},
635 {"stun.taxsee.com", 3478},
636 {"stun.teamfon.de", 3478},
637 {"stun.technosens.fr", 3478},
638 {"stun.teconisy.com", 3478},
639 {"stun.tel.lu", 3478},
640 {"stun.tel2.co.uk", 3478},
641 {"stun.telbo.com", 3478},
642 {"stun.tele2.net", 3478},
643 {"stun.telemar.it", 3478},
644 {"stun.teliax.com", 3478},
645 {"stun.telnyx.com", 3478},
646 {"stun.telonline.com", 3478},
647 {"stun.telviva.com", 3478},
648 {"stun.telz.com", 3478},
649 {"stun.telzio.com", 3478},
650 {"stun.testreach.com", 3478},
651 {"stun.textz.com", 3478},
652 {"stun.thebrassgroup.it", 3478},
653 {"stun.thfree.ru", 3478},
654 {"stun.thinkrosystem.com", 3478},
655 {"stun.threema.ch", 3478},
656 {"stun.tichiamo.it", 3478},
657 {"stun.tng.de", 3478},
658 {"stun.totalcom.info", 3478},
659 {"stun.touchcast.com", 3478},
660 {"stun.training-online.eu", 3478},
661 {"stun.trainingspace.online", 3478},
662 {"stun.transitiontown-essen.de", 3478},
663 {"stun.trivenet.it", 3478},
664 {"stun.ttmath.org", 3478},
665 {"stun.tula.nu", 3478},
666 {"stun.twt.it", 3478},
667 {"stun.uabrides.com", 3478},
668 {"stun.uavia.eu", 3478},
669 {"stun.uiltucssicilia.it", 3478},
670 {"stun.ukh.de", 3478},
671 {"stun.uls.co.za", 3478},
672 {"stun.unseen.is", 3478},
673 {"stun.url.net.au", 3478},
674 {"stun.vadacom.co.nz", 3478},
675 {"stun.var6.cn", 3478},
676 {"stun.vavadating.com", 3478},
677 {"stun.vbuzzer.com", 3478},
678 {"stun.vedamo.com", 3478},
679 {"stun.verbo.be", 3478},
680 {"stun.viagenie.ca", 3478},
681 {"stun.vietid.net", 3478},
682 {"stun.villapalagonia.it", 3478},
683 {"stun.vincross.com", 3478},
684 {"stun.vipgroup.net", 3478},
685 {"stun.viptel.sk", 3478},
686 {"stun.virishi.net", 3478},
687 {"stun.visocon.com", 3478},
688 {"stun.viva.gr", 3478},
689 {"stun.vivox.com", 3478},
690 {"stun.vnc.biz", 3478},
691 {"stun.vo.lu", 3478},
692 {"stun.voicetech.se", 3478},
693 {"stun.voicetrading.com", 3478},
694 {"stun.voip.aebc.com", 3478},
695 {"stun.voip.blackberry.com", 3478},
696 {"stun.voip.eutelia.it", 3478},
697 {"stun.voiparound.com", 3478},
698 {"stun.voipblast.com", 3478},
699 {"stun.voipbuster.com", 3478},
700 {"stun.voipbusterpro.com", 3478},
701 {"stun.voipcheap.co.uk", 3478},
702 {"stun.voipcheap.com", 3478},
703 {"stun.voipconnect.com", 3478},
704 {"stun.voipdiscount.com", 3478},
705 {"stun.voipfibre.com", 3478},
706 {"stun.voipgain.com", 3478},
707 {"stun.voipgate.com", 3478},
708 {"stun.voipgrid.nl", 3478},
709 {"stun.voipia.net", 3478},
710 {"stun.voipinfocenter.com", 3478},
711 {"stun.voippro.com", 3478},
712 {"stun.voipraider.com", 3478},
713 {"stun.voiprakyat.or.id", 3478},
714 {"stun.voipstreet.com", 3478},
715 {"stun.voipstunt.com", 3478},
716 {"stun.voipvoice.it", 3478},
717 {"stun.voipwise.com", 3478},
718 {"stun.voipxs.nl", 3478},
719 {"stun.voipzoom.com", 3478},
720 {"stun.vomessen.de", 3478},
721 {"stun.voxgratia.org", 3478},
722 {"stun.voxox.com", 3478},
723 {"stun.voys.nl", 3478},
724 {"stun.vozelia.com", 3478},
725 {"stun.voztele.com", 3478},
726 {"stun.voztovoice.org", 3478},
727 {"stun.waterpolopalermo.it", 3478},
728 {"stun.watsh.tv", 3478},
729 {"stun.wcoil.com", 3478},
730 {"stun.webcalldirect.com", 3478},
731 {"stun.webfreak.org", 3478},
732 {"stun.webitel.ua", 3478},
733 {"stun.webmatrix.com.br", 3478},
734 {"stun.webscience-journal.net", 3478},
735 {"stun.weepee.org", 3478},
736 {"stun.weilnetz.de", 3478},
737 {"stun.welten-wechsler.de", 3478},
738 {"stun.wemag.com", 3478},
739 {"stun.westtel.ky", 3478},
740 {"stun.whc.net", 3478},
741 {"stun.wia.cz", 3478},
742 {"stun.wifirst.net", 3478},
743 {"stun.wtfismyip.com", 3478},
744 {"stun.wxnz.net", 3478},
745 {"stun.xn----8sbcoa5btidn9i.xn--p1ai", 3478},
746 {"stun.xten.com", 3478},
747 {"stun.xtratelecom.es", 3478},
748 {"stun.xyzz.work", 3478},
749 {"stun.yangutu.com", 3478},
750 {"stun.yesdates.com", 3478},
751 {"stun.yeymo.com", 3478},
752 {"stun.yollacalls.com", 3478},
753 {"stun.yy.com", 3478},
754 {"stun.zadarma.com", 3478},
755 {"stun.zentauron.de", 3478},
756 {"stun.zepter.ru", 3478},
757 {"stun.zombiegrinder.com", 3478},
758 {"stun.zottel.net", 3478},
759 {"stun.zuckschwerdt.org", 3478},
760 {"stun1.faktortel.com.au", 3478},
761 {"stun1.l.google.com", 19302},
762 {"stun1.l.google.com", 19305},
763 {"stun2.l.google.com", 19302},
764 {"stun2.l.google.com", 19305},
765 {"stun3.l.google.com", 19302},
766 {"stun3.l.google.com", 19305},
767 {"stun4.l.google.com", 19302},
768 {"stun4.l.google.com", 19305}
772 /* wrapper to send an STUN message */
773 static int stun_send(int s, struct sockaddr_in *dst, struct stun_header *resp)
775 return sendto(s, (const char *)resp, ntohs(resp->msglen) + sizeof(*resp), 0,
776 (struct sockaddr *)dst, sizeof(*dst));
779 /* helper function to generate a random request id */
780 static uint64_t randfiller = GetRand(std::numeric_limits<uint64_t>::max());
781 static void stun_req_id(struct stun_header *req)
783 const uint64_t *S_block = (const uint64_t *)StunSrvList;
784 req->id.id[0] = GetRandInt(std::numeric_limits<int32_t>::max());
785 req->id.id[1] = GetRandInt(std::numeric_limits<int32_t>::max());
786 req->id.id[2] = GetRandInt(std::numeric_limits<int32_t>::max());
787 req->id.id[3] = GetRandInt(std::numeric_limits<int32_t>::max());
789 req->id.id[0] |= 0x55555555;
790 req->id.id[1] &= 0x55555555;
791 req->id.id[2] |= 0x55555555;
792 req->id.id[3] &= 0x55555555;
795 uint32_t s_elm = S_block[(uint8_t)randfiller];
796 randfiller ^= (randfiller << 5) | (randfiller >> (64 - 5));
797 randfiller += s_elm ^ x;
798 req->id.id[x & 3] ^= randfiller + (randfiller >> 13);
802 /* callback type to be invoked on stun responses. */
803 typedef int (stun_cb_f)(struct stun_attr *attr, void *arg);
805 /* handle an incoming STUN message.
807 * Do some basic sanity checks on packet size and content,
808 * try to extract a bit of information, and possibly reply.
809 * At the moment this only processes BIND requests, and returns
810 * the externally visible address of the request.
811 * If a callback is specified, invoke it with the attribute.
813 static int stun_handle_packet(int s, struct sockaddr_in *src,
814 unsigned char *data, size_t len, stun_cb_f *stun_cb, void *arg)
816 struct stun_header *hdr = (struct stun_header *)data;
817 struct stun_attr *attr;
821 /* On entry, 'len' is the length of the udp payload. After the
822 * initial checks it becomes the size of unprocessed options,
823 * while 'data' is advanced accordingly.
825 if (len < sizeof(struct stun_header))
828 len -= sizeof(struct stun_header);
829 data += sizeof(struct stun_header);
830 x = ntohs(hdr->msglen); /* len as advertised in the message */
835 if (len < sizeof(struct stun_attr)) {
839 attr = (struct stun_attr *)data;
840 /* compute total attribute length */
841 x = ntohs(attr->len) + sizeof(struct stun_attr);
847 //if (stun_process_attr(&st, attr)) {
851 /* Clear attribute id: in case previous entry was a string,
852 * this will act as the terminator for the string.
858 /* Null terminate any string.
859 * XXX NOTE, we write past the size of the buffer passed by the
860 * caller, so this is potentially dangerous. The only thing that
861 * saves us is that usually we read the incoming message in a
866 /* Now prepare to generate a reply, which at the moment is done
867 * only for properly formed (len == 0) STUN_BINDREQ messages.
873 /* Extract the STUN_MAPPED_ADDRESS from the stun response.
874 * This is used as a callback for stun_handle_response
875 * when called from stun_request.
877 static int stun_get_mapped(struct stun_attr *attr, void *arg)
879 struct stun_addr *addr = (struct stun_addr *)(attr + 1);
880 struct sockaddr_in *sa = (struct sockaddr_in *)arg;
882 if (ntohs(attr->attr) != STUN_MAPPED_ADDRESS || ntohs(attr->len) != 8)
883 return 1; /* not us. */
884 sa->sin_port = addr->port;
885 sa->sin_addr.s_addr = addr->addr;
889 /*---------------------------------------------------------------------*/
891 static int StunRequest2(int sock, struct sockaddr_in *server, struct sockaddr_in *mapped) {
893 struct stun_header *req;
894 unsigned char reqdata[1024];
896 req = (struct stun_header *)reqdata;
898 unsigned short reqlen = 0;
901 req->msglen = htons(reqlen);
902 req->msgtype = htons(STUN_BINDREQ);
904 unsigned char reply_buf[1024];
906 struct timeval to = { STUN_TIMEOUT, 0 };
907 struct sockaddr_in src;
914 int res = stun_send(sock, server, req);
919 res = select(sock + 1, &rfds, NULL, NULL, &to);
920 if (res <= 0) /* timeout or error */
922 memset(&src, 0, sizeof(src));
923 srclen = sizeof(src);
924 /* XXX pass -1 in the size, because stun_handle_packet might
925 * write past the end of the buffer.
927 res = recvfrom(sock, (char *)reply_buf, sizeof(reply_buf) - 1,
928 0, (struct sockaddr *)&src, &srclen);
931 memset(mapped, 0, sizeof(struct sockaddr_in));
932 return stun_handle_packet(sock, &src, reply_buf, res, stun_get_mapped, mapped);
935 /*---------------------------------------------------------------------*/
936 static int StunRequest(const char *host, uint16_t port, struct sockaddr_in *mapped) {
937 struct hostent *hostinfo = gethostbyname(host);
941 SOCKET sock = INVALID_SOCKET;
942 struct sockaddr_in server, client;
943 memset(&server, 0, sizeof(server));
944 memset(&client, 0, sizeof(client));
945 server.sin_family = client.sin_family = AF_INET;
947 server.sin_addr = *(struct in_addr*) hostinfo->h_addr;
948 server.sin_port = htons(port);
950 sock = socket(AF_INET, SOCK_DGRAM, 0);
951 if(sock == INVALID_SOCKET)
954 client.sin_addr.s_addr = htonl(INADDR_ANY);
957 if(bind(sock, (struct sockaddr*)&client, sizeof(client)) >= 0)
958 rc = StunRequest2(sock, &server, mapped);
963 /*---------------------------------------------------------------------*/
964 // Input: two random values (pos, step) for generate uniuqe way over server
966 // Output: populate struct struct mapped
969 int GetExternalIPbySTUN(uint64_t rnd, struct sockaddr_in *mapped, const char **srv) {
974 rnd = (rnd >> 8) | 0xff00000000000000LL;
975 step = rnd % StunSrvListQty;
979 for(attempt = 1; attempt < StunSrvListQty * 2; attempt++) {
980 pos = (pos + step) % StunSrvListQty;
981 int rc = StunRequest(*srv = StunSrvList[pos].name, StunSrvList[pos].port, mapped);
984 // fprintf(stderr, "Lookup: %s:%u\t%s\t%d\n", StunSrvList[pos].name,
985 // StunSrvList[pos].port, inet_ntoa(mapped->sin_addr), rc);