Merge branch 'main' into v2

* main:
  feat(config): add option for audit file (fixes #9481) (#10066)
  chore(api): log X-Forwarded-For (#10035)
  chore(gui): update dependency copyrights, add script for periodic maintenance (#10067)
  chore(gui, man, authors): update docs, translations, and contributors
  chore(syncthing): remove support for TLS 1.2 sync connections (#10064)
  fix(osutil): give threads same I/O priority on Linux (#10063)
  chore(stun): switch lookup warning to debug level
  chore(gui, man, authors): update docs, translations, and contributors
This commit is contained in:
Jakob Borg
2025-04-24 08:47:52 +07:00
31 changed files with 716 additions and 109 deletions

View File

@@ -277,6 +277,7 @@ Oyebanji Jacob Mayowa <oyebanji05@gmail.com>
Pablo <pbaeyens31+github@gmail.com>
Pascal Jungblut (pascalj) <github@pascalj.com> <mail@pascal-jungblut.com>
Paul Brit <paulbrit44@gmail.com>
Paul Donald <newtwen+github@gmail.com>
Pawel Palenica (qepasa) <pawelpalenica11@gmail.com>
Paweł Rozlach <vespian@users.noreply.github.com>
perewa <cavalcante.ten@gmail.com>
@@ -327,6 +328,7 @@ Syncthing Release Automation <release@syncthing.net>
Sébastien WENSKE <sebastien@wenske.fr>
Taylor Khan (nelsonkhan) <nelsonkhan@gmail.com>
Terrance <git@terrance.allofti.me>
TheCreeper <TheCreeper@users.noreply.github.com>
Thomas <9749173+uhthomas@users.noreply.github.com>
Thomas Hipp <thomashipp@gmail.com>
Tim Abell (timabell) <tim@timwise.co.uk>

View File

@@ -23,6 +23,7 @@ case "${1:-default}" in
prerelease)
script authors
script copyrights
build weblate
pushd man ; ./refresh.sh ; popd
git add -A gui man AUTHORS

View File

@@ -533,8 +533,19 @@ func (c *serveCmd) syncthingMain() {
Verbose: c.Verbose,
DBMaintenanceInterval: c.DBMaintenanceInterval,
}
if c.Audit {
appOpts.AuditWriter = auditWriter(c.AuditFile)
if c.Audit || cfgWrapper.Options().AuditEnabled {
l.Infoln("Auditing is enabled.")
auditFile := cfgWrapper.Options().AuditFile
// Ignore config option if command-line option is set
if c.AuditFile != "" {
l.Debugln("Using the audit file from the command-line parameter.")
auditFile = c.AuditFile
}
appOpts.AuditWriter = auditWriter(auditFile)
}
app, err := syncthing.New(cfgWrapper, sdb, evLogger, cert, appOpts)

View File

@@ -9,9 +9,15 @@
"Add Folder": "Lisa kaust",
"Add new folder?": "Lisa uus kaust?",
"Address": "Aadress",
"Addresses": "Aadressid",
"All Data": "Kõik andmed",
"All Time": "Kõik ajad",
"Allowed Networks": "Lubatud võrgud",
"Alphabetic": "Tähestikuline",
"Automatic upgrades": "Automaatsed uuendused",
"Be careful!": "Ettevaatust!",
"Cancel": "Loobu",
"Changelog": "Muudatuste nimekiri",
"Close": "Sulge",
"Configured": "Seadistatud",
"Connection Error": "Ühenduse viga",

View File

@@ -30,7 +30,7 @@
<h4 class="text-center" translate>The Syncthing Authors</h4>
<div class="row">
<div class="col-md-12" id="contributor-list">
Jakob Borg, Audrius Butkevicius, Jesse Lucas, Simon Frei, Tomasz Wilczyński, Alexander Graf, Alexandre Viau, Anderson Mesquita, André Colomb, Antony Male, Ben Schulz, Caleb Callaway, Daniel Harte, Emil Lundberg, Eric P, Evgeny Kuznetsov, Lars K.W. Gohlke, Lode Hoste, Michael Ploujnikov, Nate Morrison, Philippe Schommers, Ross Smith II, Ryan Sullivan, Sergey Mishin, Stefan Tatschner, Wulf Weich, bt90, greatroar, Aaron Bieber, Adam Piggott, Adel Qalieh, Alan Pope, Alberto Donato, Aleksey Vasenev, Alessandro G., Alex Ionescu, Alex Lindeman, Alex Xu, Alexander Seiler, Alexandre Alves, Aman Gupta, Anatoli Babenia, Andreas Sommer, Andrew Dunham, Andrew Meyer, Andrew Rabert, Andrey D, Anjan Momi, Anthony Goeckner, Antoine Lamielle, Anur, Aranjedeath, Arkadiusz Tymiński, Aroun, Arthur Axel fREW Schmidt, Artur Zubilewicz, Aurélien Rainone, BAHADIR YILMAZ, Bart De Vries, Beat Reichenbach, Ben Curthoys, Ben Shepherd, Ben Sidhom, Benedikt Heine, Benedikt Morbach, Benjamin Nater, Benno Fünfstück, Benny Ng, Boqin Qin, Boris Rybalkin, Brandon Philips, Brendan Long, Brian R. Becker, Carsten Hagemann, Catfriend1, Cathryne Linenweaver, Cedric Staniewski, Chih-Hsuan Yen, Choongkyu, Chris Howie, Chris Joel, Chris Tonkinson, Christian Kujau, Christian Prescott, Colin Kennedy, Cromefire_, Cyprien Devillez, Dale Visser, Dan, Daniel Barczyk, Daniel Bergmann, Daniel Martí, Daniel Padrta, Darshil Chanpura, David Rimmer, DeflateAwning, Denis A., Dennis Wilson, DerRockWolf, Devon G. Redekopp, Dimitri Papadopoulos Orfanos, Dmitry Saveliev, Domenic Horner, Dominik Heidler, Elias Jarlebring, Elliot Huffman, Emil Hessman, Eng Zer Jun, Eric Lesiuta, Erik Meitner, Evan Spensley, Federico Castagnini, Felix, Felix Ableitner, Felix Lampe, Felix Unterpaintner, Francois-Xavier Gsell, Frank Isemann, Gahl Saraf, Gilli Sigurdsson, Gleb Sinyavskiy, Graham Miln, Greg, Gusted, Han Boetes, HansK-p, Harrison Jones, Heiko Zuerker, Hireworks, Hugo Locurcio, Iain Barnett, Ian Johnson, Ikko Ashimine, Ilya Brin, Iskander Sharipov, Jaakko Hannikainen, Jacek Szafarkiewicz, Jack Croft, Jacob, Jake Peterson, James O'Beirne, James Patterson, Jaroslav Lichtblau, Jaroslav Malec, Jaspitta, Jauder Ho, Jaya Chithra, Jaya Kumar, Jeffery To, Jens Diemer, Jerry Jacobs, Jochen Voss, Johan Andersson, Johan Vromans, John Rinehart, Jonas Thelemann, Jonathan, Jonathan Cross, Jonta, Jose Manuel Delicado, Julian Lehrhuber, Jörg Thalheim, Jędrzej Kula, K.B.Dharun Krishna, Kalle Laine, Kapil Sareen, Karol Różycki, Kebin Liu, Keith Harrison, Keith Turner, Kelong Cong, Ken'ichi Kamada, Kevin Allen, Kevin Bushiri, Kevin White, Jr., Kurt Fitzner, LSmithx2, Lars Lehtonen, Laurent Arnoud, Laurent Etiemble, Leo Arias, Liu Siyuan, Lord Landon Agahnim, Lukas Lihotzki, Luke Hamburg, Majed Abdulaziz, Marc Laporte, Marc Pujol, Marcin Dziadus, Marcus B Spencer, Marcus Legendre, Mario Majila, Mark Pulford, Martchus, Martin Polehla, Mateusz Naściszewski, Mateusz Ż, Matic Potočnik, Matt Burke, Matt Robenolt, Matteo Ruina, Maurizio Tomasi, Max, Max Schulze, MaximAL, Maxime Thirouin, Maximilian, MichaIng, Michael Jephcote, Michael Rienstra, Michael Tilli, Migelo, Mike Boone, MikeLund, MikolajTwarog, Mingxuan Lin, Naveen, Nicholas Rishel, Nick Busey, Nico Stapelbroek, Nicolas Braud-Santoni, Nicolas Perraut, Niels Peter Roest, Nils Jakobi, NinoM4ster, Nitroretro, NoLooseEnds, Oliver Freyermuth, Otiel, Oyebanji Jacob Mayowa, Pablo, Pascal Jungblut, Paul Brit, Pawel Palenica, Paweł Rozlach, Peter Badida, Peter Dave Hello, Peter Hoeg, Peter Marquardt, Phani Rithvij, Phil Davis, Phill Luby, Pier Paolo Ramon, Piotr Bejda, Pramodh KP, Quentin Hibon, Rahmi Pruitt, Richard Hartmann, Robert Carosi, Roberto Santalla, Robin Schoonover, Roman Zaynetdinov, Ruslan Yevdokymov, Ryan Qian, Sacheendra Talluri, Scott Klupfel, Sertonix, Severin von Wnuck-Lipinski, Shaarad Dalvi, Simon Mwepu, Simon Pickup, Sly_tom_cat, Sonu Kumar Saw, Stefan Kuntz, Steven Eckhoff, Suhas Gundimeda, Sven Bachmann, Sébastien WENSKE, Taylor Khan, Terrance, Thomas, Thomas Hipp, Tim Abell, Tim Howes, Tim Nordenfur, Tobias Frölich, Tobias Klauser, Tobias Nygren, Tobias Tom, Tom Jakubowski, Tommy Thorn, Tommy van der Vorst, Tully Robinson, Tyler Brazier, Tyler Kropp, Unrud, Veeti Paananen, Victor Buinsky, Vik, Vil Brekin, Vladimir Rusinov, WangXi, Will Rouesnel, William A. Kennington III, Xavier O., Yannic A., andresvia, andyleap, boomsquared, chenrui, chucic, cjc7373, cui fliter, d-volution, dashangcun, derekriemer, desbma, diemade, digital, entity0xfe, georgespatton, ghjklw, guangwu, gudvinr, ignacy123, janost, jaseg, jelle van der Waa, jtagcat, klemens, kylosus, luchenhan, luzpaz, marco-m, mathias4833, maxice8, mclang, mv1005, nf, orangekame3, otbutz, overkill, perewa, polyfloyd, red_led, rubenbe, sec65, vapatel2, villekalliomaki, wangguoliang, wouter bolsterlee, xarx00, xjtdy888, 佛跳墙, 落心
Jakob Borg, Audrius Butkevicius, Jesse Lucas, Simon Frei, Tomasz Wilczyński, Alexander Graf, Alexandre Viau, Anderson Mesquita, André Colomb, Antony Male, Ben Schulz, Caleb Callaway, Daniel Harte, Emil Lundberg, Eric P, Evgeny Kuznetsov, Lars K.W. Gohlke, Lode Hoste, Michael Ploujnikov, Nate Morrison, Philippe Schommers, Ross Smith II, Ryan Sullivan, Sergey Mishin, Stefan Tatschner, Wulf Weich, bt90, greatroar, Aaron Bieber, Adam Piggott, Adel Qalieh, Alan Pope, Alberto Donato, Aleksey Vasenev, Alessandro G., Alex Ionescu, Alex Lindeman, Alex Xu, Alexander Seiler, Alexandre Alves, Aman Gupta, Anatoli Babenia, Andreas Sommer, Andrew Dunham, Andrew Meyer, Andrew Rabert, Andrey D, Anjan Momi, Anthony Goeckner, Antoine Lamielle, Anur, Aranjedeath, Arkadiusz Tymiński, Aroun, Arthur Axel fREW Schmidt, Artur Zubilewicz, Aurélien Rainone, BAHADIR YILMAZ, Bart De Vries, Beat Reichenbach, Ben Curthoys, Ben Shepherd, Ben Sidhom, Benedikt Heine, Benedikt Morbach, Benjamin Nater, Benno Fünfstück, Benny Ng, Boqin Qin, Boris Rybalkin, Brandon Philips, Brendan Long, Brian R. Becker, Carsten Hagemann, Catfriend1, Cathryne Linenweaver, Cedric Staniewski, Chih-Hsuan Yen, Choongkyu, Chris Howie, Chris Joel, Chris Tonkinson, Christian Kujau, Christian Prescott, Colin Kennedy, Cromefire_, Cyprien Devillez, Dale Visser, Dan, Daniel Barczyk, Daniel Bergmann, Daniel Martí, Daniel Padrta, Darshil Chanpura, David Rimmer, DeflateAwning, Denis A., Dennis Wilson, DerRockWolf, Devon G. Redekopp, Dimitri Papadopoulos Orfanos, Dmitry Saveliev, Domenic Horner, Dominik Heidler, Elias Jarlebring, Elliot Huffman, Emil Hessman, Eng Zer Jun, Eric Lesiuta, Erik Meitner, Evan Spensley, Federico Castagnini, Felix, Felix Ableitner, Felix Lampe, Felix Unterpaintner, Francois-Xavier Gsell, Frank Isemann, Gahl Saraf, Gilli Sigurdsson, Gleb Sinyavskiy, Graham Miln, Greg, Gusted, Han Boetes, HansK-p, Harrison Jones, Heiko Zuerker, Hireworks, Hugo Locurcio, Iain Barnett, Ian Johnson, Ikko Ashimine, Ilya Brin, Iskander Sharipov, Jaakko Hannikainen, Jacek Szafarkiewicz, Jack Croft, Jacob, Jake Peterson, James O'Beirne, James Patterson, Jaroslav Lichtblau, Jaroslav Malec, Jaspitta, Jauder Ho, Jaya Chithra, Jaya Kumar, Jeffery To, Jens Diemer, Jerry Jacobs, Jochen Voss, Johan Andersson, Johan Vromans, John Rinehart, Jonas Thelemann, Jonathan, Jonathan Cross, Jonta, Jose Manuel Delicado, Julian Lehrhuber, Jörg Thalheim, Jędrzej Kula, K.B.Dharun Krishna, Kalle Laine, Kapil Sareen, Karol Różycki, Kebin Liu, Keith Harrison, Keith Turner, Kelong Cong, Ken'ichi Kamada, Kevin Allen, Kevin Bushiri, Kevin White, Jr., Kurt Fitzner, LSmithx2, Lars Lehtonen, Laurent Arnoud, Laurent Etiemble, Leo Arias, Liu Siyuan, Lord Landon Agahnim, Lukas Lihotzki, Luke Hamburg, Majed Abdulaziz, Marc Laporte, Marc Pujol, Marcin Dziadus, Marcus B Spencer, Marcus Legendre, Mario Majila, Mark Pulford, Martchus, Martin Polehla, Mateusz Naściszewski, Mateusz Ż, Matic Potočnik, Matt Burke, Matt Robenolt, Matteo Ruina, Maurizio Tomasi, Max, Max Schulze, MaximAL, Maxime Thirouin, Maximilian, MichaIng, Michael Jephcote, Michael Rienstra, Michael Tilli, Migelo, Mike Boone, MikeLund, MikolajTwarog, Mingxuan Lin, Naveen, Nicholas Rishel, Nick Busey, Nico Stapelbroek, Nicolas Braud-Santoni, Nicolas Perraut, Niels Peter Roest, Nils Jakobi, NinoM4ster, Nitroretro, NoLooseEnds, Oliver Freyermuth, Otiel, Oyebanji Jacob Mayowa, Pablo, Pascal Jungblut, Paul Brit, Paul Donald, Pawel Palenica, Paweł Rozlach, Peter Badida, Peter Dave Hello, Peter Hoeg, Peter Marquardt, Phani Rithvij, Phil Davis, Phill Luby, Pier Paolo Ramon, Piotr Bejda, Pramodh KP, Quentin Hibon, Rahmi Pruitt, Richard Hartmann, Robert Carosi, Roberto Santalla, Robin Schoonover, Roman Zaynetdinov, Ruslan Yevdokymov, Ryan Qian, Sacheendra Talluri, Scott Klupfel, Sertonix, Severin von Wnuck-Lipinski, Shaarad Dalvi, Simon Mwepu, Simon Pickup, Sly_tom_cat, Sonu Kumar Saw, Stefan Kuntz, Steven Eckhoff, Suhas Gundimeda, Sven Bachmann, Sébastien WENSKE, Taylor Khan, Terrance, TheCreeper, Thomas, Thomas Hipp, Tim Abell, Tim Howes, Tim Nordenfur, Tobias Frölich, Tobias Klauser, Tobias Nygren, Tobias Tom, Tom Jakubowski, Tommy Thorn, Tommy van der Vorst, Tully Robinson, Tyler Brazier, Tyler Kropp, Unrud, Veeti Paananen, Victor Buinsky, Vik, Vil Brekin, Vladimir Rusinov, WangXi, Will Rouesnel, William A. Kennington III, Xavier O., Yannic A., andresvia, andyleap, boomsquared, chenrui, chucic, cjc7373, cui fliter, d-volution, dashangcun, derekriemer, desbma, diemade, digital, entity0xfe, georgespatton, ghjklw, guangwu, gudvinr, ignacy123, janost, jaseg, jelle van der Waa, jtagcat, klemens, kylosus, luchenhan, luzpaz, marco-m, mathias4833, maxice8, mclang, mv1005, nf, orangekame3, otbutz, overkill, perewa, polyfloyd, red_led, rubenbe, sec65, vapatel2, villekalliomaki, wangguoliang, wouter bolsterlee, xarx00, xjtdy888, 佛跳墙, 落心
</div>
</div>
</div>
@@ -38,48 +38,94 @@ Jakob Borg, Audrius Butkevicius, Jesse Lucas, Simon Frei, Tomasz Wilczyński, Al
<div id="about-includes" class="tab-pane">
<p translate>Syncthing includes the following software or portions thereof:</p>
<ul class="list-unstyled two-columns" id="copyright-notices">
<li><a href="http://getbootstrap.com/">Bootstrap</a>, Copyright &copy; 2011-2016 Twitter, Inc.</li>
<li><a href="https://getbootstrap.com/">Bootstrap</a>, Copyright &copy; 2011-2016 Twitter, Inc.</li>
<li><a href="https://angularjs.org/">AngularJS</a>, Copyright &copy; 2010-2014, 2016 Google, Inc.</li>
<li><a href="http://www.daterangepicker.com/">Date Range Picker</a>, Copyright &copy; 2012-2018 Dan Grossman.</li>
<li><a href="https://www.daterangepicker.com/">Date Range Picker</a>, Copyright &copy; 2012-2018 Dan Grossman.</li>
<li><a href="https://github.com/mar10/fancytree">JQuery Fancytree Plugin</a>, Copyright &copy; 2008-2018 Martin Wendt.</li>
<li><a href="https://fontawesome.com/">Font Awesome</a>Copyright &copy; 2024 Fonticons, Inc.</li>
<li><a href="https://forkaweso.me/Fork-Awesome/">Fork Awesome</a>, Copyright &copy; 2018 Dave Gandy &amp; Fork Awesome.</li>
<li><a href="http://jquery.com/">jQuery JavaScript Library</a>, Copyright &copy; jQuery Foundation and other contributors.</li>
<li><a href="http://momentjs.com/">moment.js</a>, Copyright &copy; JS Foundation and other contributors.</li>
<li><a href="https://evanhahn.github.io/HumanizeDuration.js/">HumanDuration.js</a>, Copyright &copy; 2013-2024 Evan Hahn, portions copyright &copy; 2024 Ross Smith II.</li>
<li><a href="https://jquery.com/">jQuery JavaScript Library</a>, Copyright &copy; jQuery Foundation and other contributors.</li>
<li><a href="https://leafletjs.com/">leaflet.js</a>, Copyright &copy; 2010-2025 Volodymyr Agafonkin, Copyright &copy; 2010-2011 CloudMade.</li>
<li><a href="https://momentjs.com/">moment.js</a>, Copyright &copy; JS Foundation and other contributors.</li>
<li><a href="https://golang.org/">The Go Programming Language</a>, Copyright &copy; 2009 The Go Authors.</li>
<li><a href="https://prometheus.io/">Prometheus</a>, Copyright &copy; 2012-2015 The Prometheus Authors.</li>
<li><a href="https://github.com/AudriusButkevicius/go-nat-pmp">AudriusButkevicius/go-nat-pmp</a>, Copyright &copy; 2013 John Howard Palevich.</li>
<li><a href="https://github.com/AudriusButkevicius/recli">AudriusButkevicius/recli</a>, Copyright &copy; 2019 Audrius Butkevicius.</li>
<li><a href="https://github.com/Azure/azure-sdk-for-go">Azure/azure-sdk-for-go</a>, Copyright &copy; Microsoft Corporation.</li>
<li><a href="https://github.com/Azure/go-ntlmssp">Azure/go-ntlmssp</a>, Copyright &copy; 2016 Microsoft.</li>
<li><a href="https://github.com/alecthomas/kong">alecthomas/kong</a>, Copyright &copy; 2018 Alec Thomas.</li>
<li><a href="https://github.com/aws/aws-sdk-go">aws/aws-sdk-go</a>, Copyright &copy; 2015 Amazon.com, Inc. or its affiliates, Copyright 2014-2015 Stripe, Inc.</li>
<li><a href="https://github.com/beorn7/perks">beorn7/perks</a>, Copyright &copy; 2013 Blake Mizerany.</li>
<li><a href="https://github.com/pierrec/lz4">pierrec/lz4</a>, Copyright &copy; 2015 Pierre Curto.</li>
<li><a href="https://github.com/calmh/du">calmh/du</a>, Public domain.</li>
<li><a href="https://github.com/calmh/incontainer">calmh/incontainer</a>, Copyright &copy; 2022 calmh.</li>
<li><a href="https://github.com/calmh/xdr">calmh/xdr</a>, Copyright &copy; 2014 Jakob Borg.</li>
<li><a href="https://github.com/ccding/go-stun">ccding/go-stun</a>, Copyright &copy; 2016 Cong Ding.</li>
<li><a href="https://github.com/cenkalti/backoff">cenkalti/backoff</a>, Copyright &copy; 2014 Cenk Altı.</li>
<li><a href="https://github.com/certifi/gocertifi">certifi/gocertifi</a>, Copyright &copy; 2025, the certifi/gocertifi authors.</li>
<li><a href="https://github.com/cespare/xxhash">cespare/xxhash</a>, Copyright &copy; 2016 Caleb Spare.</li>
<li><a href="https://github.com/chmduquesne/rollinghash">chmduquesne/rollinghash</a>, Copyright &copy; 2015 Christophe-Marie Duquesne.</li>
<li><a href="https://github.com/cpuguy83/go-md2man">cpuguy83/go-md2man</a>, Copyright &copy; 2014 Brian Goff.</li>
<li><a href="https://github.com/d4l3k/messagediff">d4l3k/messagediff</a>, Copyright &copy; 2015 Tristan Rice.</li>
<li><a href="https://github.com/davecgh/go-spew">davecgh/go-spew</a>, Copyright &copy; 2012-2016 Dave Collins <dave@davec.name>.</li>
<li><a href="https://github.com/ebitengine/purego">ebitengine/purego</a>, Copyright &copy; 2022 The Ebitengine Authors.</li>
<li><a href="https://github.com/fsnotify/fsnotify">fsnotify/fsnotify</a>, Copyright &copy; 2012 The Go Authors.</li>
<li><a href="https://github.com/getsentry/raven-go">getsentry/raven-go</a>, Copyright &copy; 2013 Apollic Software, LLC.</li>
<li><a href="https://github.com/go-asn1-ber/asn1-ber">go-asn1-ber/asn1-ber</a>, Copyright &copy; 2011-2015 Michael Mitton (mmitton@gmail.com).</li>
<li><a href="https://github.com/go-ldap/ldap">go-ldap/ldap</a>, Copyright &copy; 2011-2015 Michael Mitton (mmitton@gmail.com).</li>
<li><a href="https://github.com/go-ole/go-ole">go-ole/go-ole</a>, Copyright &copy; 2013-2017 Yasuhiro Matsumoto, <mattn.jp@gmail.com>.</li>
<li><a href="https://github.com/go-task/slim-sprig">go-task/slim-sprig</a>, Copyright &copy; 2013-2020 Masterminds.</li>
<li><a href="https://github.com/uber-go/automaxprocs">go.uber.org/automaxprocs</a>, Copyright &copy; 2017 Uber Technologies, Inc.</li>
<li><a href="https://github.com/uber-go/mock">go.uber.org/mock</a>, Copyright &copy; 2010-2022 Google LLC.</li>
<li><a href="https://github.com/gobwas/glob">gobwas/glob</a>, Copyright &copy; 2016 Sergey Kamardin.</li>
<li><a href="https://github.com/golang/groupcache">golang/groupcache</a>, Copyright &copy; 2013 Google Inc.</li>
<li><a href="https://github.com/golang/protobuf">golang/protobuf</a>, Copyright &copy; 2010 The Go Authors.</li>
<li><a href="https://github.com/gofrs/flock">gofrs/flock</a>, Copyright &copy; 2018-2025, The Gofrs.</li>
<li><a href="https://github.com/golang/snappy">golang/snappy</a>, Copyright &copy; 2011 The Snappy-Go Authors.</li>
<li><a href="https://github.com/protocolbuffers/protobuf-go">google.golang.org/protobuf</a>, Copyright &copy; 2018 The Go Authors.</li>
<li><a href="https://github.com/google/pprof">google/pprof</a>, Copyright &copy; 2016 Google Inc.</li>
<li><a href="https://github.com/google/uuid">google/uuid</a>, Copyright &copy; 2009,2014 Google Inc.</li>
<li><a href="https://github.com/go-yaml/yaml">gopkg.in/yaml.v3</a>, Copyright &copy; 2006-2010 Kirill Simonov.</li>
<li><a href="https://github.com/greatroar/blobloom">greatroar/blobloom</a>, Copyright &copy; 2020-2024 the Blobloom authors.</li>
<li><a href="https://github.com/hashicorp/errwrap">hashicorp/errwrap</a>, Copyright &copy; 2014 HashiCorp, Inc.</li>
<li><a href="https://github.com/hashicorp/go-multierror">hashicorp/go-multierror</a>, Copyright &copy; 2014 HashiCorp, Inc.</li>
<li><a href="https://github.com/hashicorp/golang-lru">hashicorp/golang-lru</a>, Copyright &copy; 2014 HashiCorp, Inc.</li>
<li><a href="https://github.com/jackpal/gateway">jackpal/gateway</a>, Copyright &copy; 2010 Jack Palevich.</li>
<li><a href="https://github.com/jmoiron/sqlx">jmoiron/sqlx</a>, Copyright &copy; 2013 Jason Moiron.</li>
<li><a href="https://github.com/jackpal/go-nat-pmp">jackpal/go-nat-pmp</a>, Copyright 2013 John Howard Palevich.</li>
<li><a href="https://github.com/jmespath/go-jmespath">jmespath/go-jmespath</a>, Copyright &copy; 2015 James Saryerwinnie.</li>
<li><a href="https://github.com/julienschmidt/httprouter">julienschmidt/httprouter</a>, Copyright &copy; 2013, Julien Schmidt.</li>
<li><a href="https://github.com/kballard/go-shellquote">kballard/go-shellquote</a>, Copyright &copy; 2014 Kevin Ballard.</li>
<li><a href="https://github.com/mattn/go-isatty">mattn/go-isatty</a>, Copyright &copy; Yasuhiro MATSUMOTO.</li>
<li><a href="https://github.com/mattn/go-sqlite3">mattn/go-sqlite3</a>, Copyright &copy; 2014 Yasuhiro Matsumoto</li>
<li><a href="https://github.com/matttproud/golang_protobuf_extensions">matttproud/golang_protobuf_extensions</a>, Copyright &copy; 2012 Matt T. Proud.</li>
<li><a href="https://modernc.org/sqlite">modernc.org/sqlite</a>, Copyright &copy; 2017 The Sqlite Authors</li>
<li><a href="https://github.com/klauspost/compress">klauspost/compress</a>, Copyright &copy; 2012 The Go Authors.</li>
<li><a href="https://github.com/lufia/plan9stats">lufia/plan9stats</a>, Copyright &copy; 2019, KADOTA, Kyohei.</li>
<li><a href="https://github.com/maruel/panicparse">maruel/panicparse</a>, Copyright 2015 Marc-Antoine Ruel.</li>
<li><a href="https://github.com/maxbrunsfeld/counterfeiter">maxbrunsfeld/counterfeiter</a>, Copyright &copy; 2014 maxbrunsfeld.</li>
<li><a href="https://github.com/maxmind/geoipupdate">maxmind/geoipupdate</a>, Copyright &copy; 2018-2024 by MaxMind, Inc.</li>
<li><a href="https://github.com/miscreant/miscreant.go">miscreant/miscreant.go</a>, Copyright &copy; 2017-2019 The Miscreant Developers.</li>
<li><a href="https://github.com/munnerz/goautoneg">munnerz/goautoneg</a>, Copyright &copy; 2011, Open Knowledge Foundation Ltd.</li>
<li><a href="https://github.com/nxadm/tail">nxadm/tail</a>, Copyright &copy; 2014 ActiveState.</li>
<li><a href="https://github.com/onsi/ginkgo">onsi/ginkgo</a>, Copyright &copy; 2013-2014 Onsi Fakhouri.</li>
<li><a href="https://github.com/oschwald/geoip2-golang">oschwald/geoip2-golang</a>, Copyright &copy; 2015, Gregory J. Oschwald.</li>
<li><a href="https://github.com/oschwald/maxminddb-golang">oschwald/maxminddb-golang</a>, Copyright &copy; 2015, Gregory J. Oschwald.</li>
<li><a href="https://github.com/petermattis/goid">petermattis/goid</a>, Copyright &copy; 2015-2016 Peter Mattis.</li>
<li><a href="https://github.com/pierrec/lz4">pierrec/lz4</a>, Copyright &copy; 2015 Pierre Curto.</li>
<li><a href="https://github.com/pkg/errors">pkg/errors</a>, Copyright &copy; 2015, Dave Cheney.</li>
<li><a href="https://github.com/pmezard/go-difflib">pmezard/go-difflib</a>, Copyright &copy; 2013, Patrick Mezard.</li>
<li><a href="https://github.com/posener/complete">posener/complete</a>, Copyright &copy; 2017 Eyal Posener.</li>
<li><a href="https://github.com/power-devops/perfstat">power-devops/perfstat</a>, Copyright &copy; 2020 Power DevOps.</li>
<li><a href="https://github.com/puzpuzpuz/xsync">puzpuzpuz/xsync</a>, Copyright &copy; 2025, the puzpuzpuz/xsync authors.</li>
<li><a href="https://github.com/quic-go/quic-go">quic-go/quic-go</a>, Copyright &copy; 2016 the quic-go authors & Google, Inc.</li>
<li><a href="https://github.com/rabbitmq/amqp091-go">rabbitmq/amqp091-go</a>, Copyright &copy; 2021 VMware, Inc. or its affiliates.</li>
<li><a href="https://github.com/rcrowley/go-metrics">rcrowley/go-metrics</a>, Copyright &copy; 2012 Richard Crowley.</li>
<li><a href="https://github.com/sasha-s/go-deadlock">sasha-s/go-deadlock</a>, Copyright &copy; 2016 sasha-s.</li>
<li><a href="https://github.com/riywo/loginshell">riywo/loginshell</a>, Copyright &copy; 2019 Ryosuke IWANAGA.</li>
<li><a href="https://github.com/russross/blackfriday">russross/blackfriday</a>, Copyright &copy; 2011 Russ Ross.</li>
<li><a href="https://github.com/shirou/gopsutil">shirou/gopsutil</a>, Copyright &copy; 2014, WAKAYAMA Shirou.</li>
<li><a href="https://github.com/kubernetes-sigs/yaml">sigs.k8s.io/yaml</a>, Copyright &copy; 2014 Sam Ghods.</li>
<li><a href="https://github.com/stretchr/objx">stretchr/objx</a>, Copyright &copy; 2014 Stretchr, Inc.</li>
<li><a href="https://github.com/stretchr/testify">stretchr/testify</a>, Copyright &copy; 2012-2020 Mat Ryer, Tyler Bunnell and contributors.</li>
<li><a href="https://github.com/syncthing/notify">syncthing/notify</a>, Copyright &copy; 2014-2015 The Notify Authors.</li>
<li><a href="https://github.com/syndtr/goleveldb">syndtr/goleveldb</a>, Copyright &copy; 2012 Suryandaru Triandana.</li>
<li><a href="https://github.com/thejerf/suture">thejerf/suture</a>, Copyright &copy; 2014-2015 Barracuda Networks, Inc.</li>
<li><a href="https://github.com/urfave/cli">urfave/cli</a>, Copyright &copy; 2016 Jeremy Saenz &amp; Contributors.</li>
<li><a href="https://github.com/tklauser/go-sysconf">tklauser/go-sysconf</a>, Copyright &copy; 2018-2022, Tobias Klauser.</li>
<li><a href="https://github.com/tklauser/numcpus">tklauser/numcpus</a>, Copyright &copy; 2018-2024 Tobias Klauser.</li>
<li><a href="https://github.com/urfave/cli">urfave/cli</a>, Copyright &copy; 2016 Jeremy Saenz & Contributors.</li>
<li><a href="https://github.com/vitrun/qart">vitrun/qart</a>, Copyright &copy; 2010-2011 The Go Authors.</li>
<li><a href="https://gopkg.in/asn1-ber.v1">gopkg.in/asn1-ber.v1</a>, Copyright &copy; 2011-2015 Michael Mitton, portions Copyright &copy; 2015-2016 go-asn1-ber Authors.</li>
<li><a href="https://gopkg.in/ldap.v2">gopkg.in/ldap.v2</a>, Copyright &copy; 2011-2015 Michael Mitton, portions Copyright &copy; 2015-2016 go-ldap Authors.</li>
<li><a href="https://golang.org">The Go Programming Language</a>, Copyright &copy; 2009 The Go Authors.</li>
<li>Font Awesome by Dave Gandy - <a href="http://fontawesome.io/">http://fontawesome.io</a></li>
<li><a href="https://github.com/willabides/kongplete">willabides/kongplete</a>, Copyright &copy; 2020 WillAbides.</li>
<li><a href="https://github.com/yusufpapurcu/wmi">yusufpapurcu/wmi</a>, Copyright &copy; 2013 Stack Exchange.</li>
</ul>
</div>

View File

@@ -18,6 +18,7 @@ import (
ldap "github.com/go-ldap/ldap/v3"
"github.com/syncthing/syncthing/lib/config"
"github.com/syncthing/syncthing/lib/events"
"github.com/syncthing/syncthing/lib/osutil"
"github.com/syncthing/syncthing/lib/rand"
)
@@ -27,15 +28,54 @@ const (
randomTokenLength = 64
)
func emitLoginAttempt(success bool, username, address string, evLogger events.Logger) {
evLogger.Log(events.LoginAttempt, map[string]interface{}{
func emitLoginAttempt(success bool, username string, r *http.Request, evLogger events.Logger) {
remoteAddress, proxy := remoteAddress(r)
evData := map[string]any{
"success": success,
"username": username,
"remoteAddress": address,
})
if !success {
l.Infof("Wrong credentials supplied during API authorization from %s", address)
"remoteAddress": remoteAddress,
}
if proxy != "" {
evData["proxy"] = proxy
}
evLogger.Log(events.LoginAttempt, evData)
if success {
return
}
if proxy != "" {
l.Infof("Wrong credentials supplied during API authorization from %s proxied by %s", remoteAddress, proxy)
} else {
l.Infof("Wrong credentials supplied during API authorization from %s", remoteAddress)
}
}
func remoteAddress(r *http.Request) (remoteAddr, proxy string) {
remoteAddr = r.RemoteAddr
remoteIP := osutil.IPFromString(r.RemoteAddr)
// parse X-Forwarded-For only if the proxy connects via unix socket, localhost or a LAN IP
var localProxy bool
if remoteIP != nil {
remoteAddr = remoteIP.String()
localProxy = remoteIP.IsLoopback() || remoteIP.IsPrivate() || remoteIP.IsLinkLocalUnicast()
} else if remoteAddr == "@" {
localProxy = true
}
if !localProxy {
return
}
forwardedAddr, _, _ := strings.Cut(r.Header.Get("X-Forwarded-For"), ",")
forwardedAddr = strings.TrimSpace(forwardedAddr)
forwardedIP := osutil.IPFromString(forwardedAddr)
if forwardedIP != nil {
proxy = remoteAddr
remoteAddr = forwardedIP.String()
}
return
}
func antiBruteForceSleep() {
@@ -152,7 +192,7 @@ func (m *basicAuthAndSessionMiddleware) passwordAuthHandler(w http.ResponseWrite
return
}
emitLoginAttempt(false, req.Username, r.RemoteAddr, m.evLogger)
emitLoginAttempt(false, req.Username, r, m.evLogger)
antiBruteForceSleep()
forbidden(w)
}
@@ -175,7 +215,7 @@ func attemptBasicAuth(r *http.Request, guiCfg config.GUIConfiguration, ldapCfg c
return usernameFromIso, true
}
emitLoginAttempt(false, username, r.RemoteAddr, evLogger)
emitLoginAttempt(false, username, r, evLogger)
antiBruteForceSleep()
return "", false
}

View File

@@ -189,7 +189,7 @@ func (m *tokenCookieManager) createSession(username string, persistent bool, w h
Path: "/",
})
emitLoginAttempt(true, username, r.RemoteAddr, m.evLogger)
emitLoginAttempt(true, username, r, m.evLogger)
}
func (m *tokenCookieManager) hasValidSession(r *http.Request) bool {

View File

@@ -92,6 +92,8 @@ func TestDefaultValues(t *testing.T) {
RawStunServers: []string{"default"},
AnnounceLANAddresses: true,
FeatureFlags: []string{},
AuditEnabled: false,
AuditFile: "",
ConnectionPriorityTCPLAN: 10,
ConnectionPriorityQUICLAN: 20,
ConnectionPriorityTCPWAN: 30,
@@ -295,6 +297,8 @@ func TestOverriddenValues(t *testing.T) {
StunKeepaliveMinS: 900,
RawStunServers: []string{"foo"},
FeatureFlags: []string{"feature"},
AuditEnabled: true,
AuditFile: "nggyu",
ConnectionPriorityTCPLAN: 40,
ConnectionPriorityQUICLAN: 45,
ConnectionPriorityTCPWAN: 50,

View File

@@ -67,22 +67,21 @@ type OptionsConfiguration struct {
AnnounceLANAddresses bool `json:"announceLANAddresses" xml:"announceLANAddresses" default:"true"`
SendFullIndexOnUpgrade bool `json:"sendFullIndexOnUpgrade" xml:"sendFullIndexOnUpgrade"`
FeatureFlags []string `json:"featureFlags" xml:"featureFlag"`
AuditEnabled bool `json:"auditEnabled" xml:"auditEnabled" default:"false"`
AuditFile string `json:"auditFile" xml:"auditFile"`
// The number of connections at which we stop trying to connect to more
// devices, zero meaning no limit. Does not affect incoming connections.
ConnectionLimitEnough int `json:"connectionLimitEnough" xml:"connectionLimitEnough"`
// The maximum number of connections which we will allow in total, zero
// meaning no limit. Affects incoming connections and prevents
// attempting outgoing connections.
ConnectionLimitMax int `json:"connectionLimitMax" xml:"connectionLimitMax"`
// When set, this allows TLS 1.2 on sync connections, where we otherwise
// default to TLS 1.3+ only.
InsecureAllowOldTLSVersions bool `json:"insecureAllowOldTLSVersions" xml:"insecureAllowOldTLSVersions"`
ConnectionPriorityTCPLAN int `json:"connectionPriorityTcpLan" xml:"connectionPriorityTcpLan" default:"10"`
ConnectionPriorityQUICLAN int `json:"connectionPriorityQuicLan" xml:"connectionPriorityQuicLan" default:"20"`
ConnectionPriorityTCPWAN int `json:"connectionPriorityTcpWan" xml:"connectionPriorityTcpWan" default:"30"`
ConnectionPriorityQUICWAN int `json:"connectionPriorityQuicWan" xml:"connectionPriorityQuicWan" default:"40"`
ConnectionPriorityRelay int `json:"connectionPriorityRelay" xml:"connectionPriorityRelay" default:"50"`
ConnectionPriorityUpgradeThreshold int `json:"connectionPriorityUpgradeThreshold" xml:"connectionPriorityUpgradeThreshold" default:"0"`
ConnectionLimitMax int `json:"connectionLimitMax" xml:"connectionLimitMax"`
ConnectionPriorityTCPLAN int `json:"connectionPriorityTcpLan" xml:"connectionPriorityTcpLan" default:"10"`
ConnectionPriorityQUICLAN int `json:"connectionPriorityQuicLan" xml:"connectionPriorityQuicLan" default:"20"`
ConnectionPriorityTCPWAN int `json:"connectionPriorityTcpWan" xml:"connectionPriorityTcpWan" default:"30"`
ConnectionPriorityQUICWAN int `json:"connectionPriorityQuicWan" xml:"connectionPriorityQuicWan" default:"40"`
ConnectionPriorityRelay int `json:"connectionPriorityRelay" xml:"connectionPriorityRelay" default:"50"`
ConnectionPriorityUpgradeThreshold int `json:"connectionPriorityUpgradeThreshold" xml:"connectionPriorityUpgradeThreshold" default:"0"`
// Legacy deprecated
DeprecatedUPnPEnabled bool `json:"-" xml:"upnpEnabled,omitempty"` // Deprecated: Do not use.
DeprecatedUPnPLeaseM int `json:"-" xml:"upnpLeaseMinutes,omitempty"` // Deprecated: Do not use.
@@ -187,7 +186,7 @@ func (opts OptionsConfiguration) StunServers() []string {
case "default":
_, records, err := net.LookupSRV("stun", "udp", "syncthing.net")
if err != nil {
l.Warnln("Unable to resolve primary STUN servers via DNS:", err)
l.Debugf("Unable to resolve primary STUN servers via DNS:", err)
}
for _, record := range records {

View File

@@ -45,6 +45,8 @@
<unackedNotificationID>asdfasdf</unackedNotificationID>
<announceLANAddresses>false</announceLANAddresses>
<featureFlag>feature</featureFlag>
<auditEnabled>true</auditEnabled>
<auditFile>nggyu</auditFile>
<connectionPriorityTcpLan>40</connectionPriorityTcpLan>
<connectionPriorityQuicLan>45</connectionPriorityQuicLan>
<connectionPriorityTcpWan>50</connectionPriorityTcpWan>

View File

@@ -15,32 +15,6 @@ import (
"syscall"
)
const ioprioClassShift = 13
type ioprioClass int
const (
ioprioClassRT ioprioClass = iota + 1
ioprioClassBE
ioprioClassIdle
)
const (
ioprioWhoProcess = iota + 1
ioprioWhoPGRP
ioprioWhoUser
)
func ioprioSet(class ioprioClass, value int) error {
res, _, err := syscall.Syscall(syscall.SYS_IOPRIO_SET,
uintptr(ioprioWhoProcess), 0,
uintptr(class)<<ioprioClassShift|uintptr(value))
if res == 0 {
return nil
}
return err
}
// SetLowPriority lowers the process CPU scheduling priority, and possibly
// I/O priority depending on the platform and OS.
func SetLowPriority() error {
@@ -89,14 +63,13 @@ func SetLowPriority() error {
}
}
// For any new process, the default is to be assigned the IOPRIO_CLASS_BE
// scheduling class. This class directly maps the BE prio level to the
// niceness of a process, determined as: io_nice = (cpu_nice + 20) / 5.
// For example, a niceness of 11 results in an I/O priority of B6.
// https://www.kernel.org/doc/Documentation/block/ioprio.txt
if err := syscall.Setpriority(syscall.PRIO_PGRP, pidSelf, wantNiceLevel); err != nil {
return fmt.Errorf("set niceness: %w", err)
}
// Best effort, somewhere to the end of the scale (0 through 7 being the
// range).
if err := ioprioSet(ioprioClassBE, 5); err != nil {
return fmt.Errorf("set I/O priority: %w", err)
}
return nil
}

View File

@@ -8,6 +8,7 @@ package osutil
import (
"net"
"strings"
)
// GetInterfaceAddrs returns the IP networks of all interfaces that are up.
@@ -46,6 +47,17 @@ func GetInterfaceAddrs(includePtP bool) ([]*net.IPNet, error) {
return nets, nil
}
func IPFromString(addr string) net.IP {
// strip the port
host, _, err := net.SplitHostPort(addr)
if err != nil {
host = addr
}
// strip IPv6 zone identifier
host, _, _ = strings.Cut(host, "%")
return net.ParseIP(host)
}
func IPFromAddr(addr net.Addr) (net.IP, error) {
switch a := addr.(type) {
case *net.TCPAddr:

View File

@@ -135,3 +135,35 @@ func TestRenameOrCopy(t *testing.T) {
}
}
}
func TestIPFromString(t *testing.T) {
t.Parallel()
cases := []struct {
in string
out string
}{
{"192.168.178.1", "192.168.178.1"},
{"192.168.178.1:8384", "192.168.178.1"},
{"fe80::20c:29ff:fe9a:46d2", "fe80::20c:29ff:fe9a:46d2"},
{"[fe80::20c:29ff:fe9a:46d2]:8384", "fe80::20c:29ff:fe9a:46d2"},
{"[fe80::20c:29ff:fe9a:46d2%eno1]:8384", "fe80::20c:29ff:fe9a:46d2"},
{"google.com", ""},
{"1.1.1.1.1", ""},
{"", ""},
}
for _, c := range cases {
ip := osutil.IPFromString(c.in)
var address string
if ip != nil {
address = ip.String()
} else {
address = ""
}
if c.out != address {
t.Fatalf("result should be %s != %s", c.out, address)
}
}
}

View File

@@ -251,13 +251,7 @@ func (a *App) startup() error {
// The TLS configuration is used for both the listening socket and outgoing
// connections.
var tlsCfg *tls.Config
if a.cfg.Options().InsecureAllowOldTLSVersions {
l.Infoln("TLS 1.2 is allowed on sync connections. This is less than optimally secure.")
tlsCfg = tlsutil.SecureDefaultWithTLS12()
} else {
tlsCfg = tlsutil.SecureDefaultTLS13()
}
tlsCfg := tlsutil.SecureDefaultTLS13()
tlsCfg.Certificates = []tls.Certificate{a.cert}
tlsCfg.NextProtos = []string{bepProtocolName}
tlsCfg.ClientAuth = tls.RequestClientCert

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "STDISCOSRV" "1" "Apr 04, 2025" "v1.29.3" "Syncthing"
.TH "STDISCOSRV" "1" "Apr 21, 2025" "v1.29.3" "Syncthing"
.SH NAME
stdiscosrv \- Syncthing Discovery Server
.SH SYNOPSIS

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "STRELAYSRV" "1" "Apr 04, 2025" "v1.29.3" "Syncthing"
.TH "STRELAYSRV" "1" "Apr 21, 2025" "v1.29.3" "Syncthing"
.SH NAME
strelaysrv \- Syncthing Relay Server
.SH SYNOPSIS

View File

@@ -28,7 +28,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-BEP" "7" "Apr 04, 2025" "v1.29.3" "Syncthing"
.TH "SYNCTHING-BEP" "7" "Apr 21, 2025" "v1.29.3" "Syncthing"
.SH NAME
syncthing-bep \- Block Exchange Protocol v1
.SH INTRODUCTION AND DEFINITIONS

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-CONFIG" "5" "Apr 04, 2025" "v1.29.3" "Syncthing"
.TH "SYNCTHING-CONFIG" "5" "Apr 21, 2025" "v1.29.3" "Syncthing"
.SH NAME
syncthing-config \- Syncthing Configuration
.SH SYNOPSIS
@@ -221,7 +221,6 @@ may no longer correspond to the defaults.
<sendFullIndexOnUpgrade>false</sendFullIndexOnUpgrade>
<connectionLimitEnough>0</connectionLimitEnough>
<connectionLimitMax>0</connectionLimitMax>
<insecureAllowOldTLSVersions>false</insecureAllowOldTLSVersions>
</options>
<remoteIgnoredDevice time=\(dq2022\-01\-09T20:02:01Z\(dq id=\(dq5SYI2FS\-LW6YAXI\-JJDYETS\-NDBBPIO\-256MWBO\-XDPXWVG\-24QPUM4\-PDW4UQU\(dq name=\(dqbugger\(dq address=\(dq192.168.0.20:22000\(dq></remoteIgnoredDevice>
<defaults>
@@ -1077,6 +1076,11 @@ header do not need this setting.
When this setting is disabled, the GUI will not send 401 responses so users
wont see browser popups prompting for username and password.
.UNINDENT
.INDENT 0.0
.TP
.B metricsWithoutAuth
If true, this allows access to the /metrics without authentication.
.UNINDENT
.SH LDAP ELEMENT
.INDENT 0.0
.INDENT 3.5
@@ -1196,7 +1200,6 @@ Search filter for user searches.
<sendFullIndexOnUpgrade>false</sendFullIndexOnUpgrade>
<connectionLimitEnough>0</connectionLimitEnough>
<connectionLimitMax>0</connectionLimitMax>
<insecureAllowOldTLSVersions>false</insecureAllowOldTLSVersions>
</options>
.EE
.UNINDENT
@@ -1533,12 +1536,6 @@ no limit. Affects incoming connections and prevents attempting outgoing
connections. The mechanism is described in detail in a \fI\%separate
chapter\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B insecureAllowOldTLSVersions
Only for compatibility with old versions of Syncthing on remote devices, as
detailed in \fI\%insecureAllowOldTLSVersions\fP\&.
.UNINDENT
.SH DEFAULTS ELEMENT
.INDENT 0.0
.INDENT 3.5

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-DEVICE-IDS" "7" "Apr 04, 2025" "v1.29.3" "Syncthing"
.TH "SYNCTHING-DEVICE-IDS" "7" "Apr 21, 2025" "v1.29.3" "Syncthing"
.SH NAME
syncthing-device-ids \- Understanding Device IDs
.sp

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-EVENT-API" "7" "Apr 04, 2025" "v1.29.3" "Syncthing"
.TH "SYNCTHING-EVENT-API" "7" "Apr 21, 2025" "v1.29.3" "Syncthing"
.SH NAME
syncthing-event-api \- Event API
.SH DESCRIPTION

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-FAQ" "7" "Apr 04, 2025" "v1.29.3" "Syncthing"
.TH "SYNCTHING-FAQ" "7" "Apr 21, 2025" "v1.29.3" "Syncthing"
.SH NAME
syncthing-faq \- Frequently Asked Questions
.INDENT 0.0

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-GLOBALDISCO" "7" "Apr 04, 2025" "v1.29.3" "Syncthing"
.TH "SYNCTHING-GLOBALDISCO" "7" "Apr 21, 2025" "v1.29.3" "Syncthing"
.SH NAME
syncthing-globaldisco \- Global Discovery Protocol v3
.SH ANNOUNCEMENTS

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-LOCALDISCO" "7" "Apr 04, 2025" "v1.29.3" "Syncthing"
.TH "SYNCTHING-LOCALDISCO" "7" "Apr 21, 2025" "v1.29.3" "Syncthing"
.SH NAME
syncthing-localdisco \- Local Discovery Protocol v4
.SH MODE OF OPERATION

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-NETWORKING" "7" "Apr 04, 2025" "v1.29.3" "Syncthing"
.TH "SYNCTHING-NETWORKING" "7" "Apr 21, 2025" "v1.29.3" "Syncthing"
.SH NAME
syncthing-networking \- Firewall Setup
.SH ROUTER SETUP

View File

@@ -28,7 +28,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-RELAY" "7" "Apr 04, 2025" "v1.29.3" "Syncthing"
.TH "SYNCTHING-RELAY" "7" "Apr 21, 2025" "v1.29.3" "Syncthing"
.SH NAME
syncthing-relay \- Relay Protocol v1
.SH WHAT IS A RELAY?

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-REST-API" "7" "Apr 04, 2025" "v1.29.3" "Syncthing"
.TH "SYNCTHING-REST-API" "7" "Apr 21, 2025" "v1.29.3" "Syncthing"
.SH NAME
syncthing-rest-api \- REST API
.sp
@@ -279,8 +279,7 @@ Returns the current configuration.
\(dqsendFullIndexOnUpgrade\(dq: false,
\(dqfeatureFlags\(dq: [],
\(dqconnectionLimitEnough\(dq: 0,
\(dqconnectionLimitMax\(dq: 0,
\(dqinsecureAllowOldTLSVersions\(dq: false
\(dqconnectionLimitMax\(dq: 0
},
\(dqremoteIgnoredDevices\(dq: [
{

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-SECURITY" "7" "Apr 04, 2025" "v1.29.3" "Syncthing"
.TH "SYNCTHING-SECURITY" "7" "Apr 21, 2025" "v1.29.3" "Syncthing"
.SH NAME
syncthing-security \- Security Principles
.sp

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-STIGNORE" "5" "Apr 04, 2025" "v1.29.3" "Syncthing"
.TH "SYNCTHING-STIGNORE" "5" "Apr 21, 2025" "v1.29.3" "Syncthing"
.SH NAME
syncthing-stignore \- Prevent files from being synchronized to other nodes
.SH SYNOPSIS

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-VERSIONING" "7" "Apr 04, 2025" "v1.29.3" "Syncthing"
.TH "SYNCTHING-VERSIONING" "7" "Apr 21, 2025" "v1.29.3" "Syncthing"
.SH NAME
syncthing-versioning \- Keep automatic backups of deleted files by other nodes
.sp

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING" "1" "Apr 04, 2025" "v1.29.3" "Syncthing"
.TH "SYNCTHING" "1" "Apr 21, 2025" "v1.29.3" "Syncthing"
.SH NAME
syncthing \- Syncthing
.SH SYNOPSIS

489
script/copyrights.go Normal file
View File

@@ -0,0 +1,489 @@
// Copyright (C) 2025 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.
//go:build ignore
// +build ignore
// Updates the list of software copyrights in aboutModalView.html based on the
// output of `go mod graph`.
package main
import (
"bufio"
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"net/url"
"os"
"os/exec"
"regexp"
"slices"
"strconv"
"strings"
"time"
"golang.org/x/net/html"
)
var copyrightMap = map[string]string{
// https://github.com/aws/aws-sdk-go/blob/main/NOTICE.txt#L2
"aws/aws-sdk-go": "Copyright &copy; 2015 Amazon.com, Inc. or its affiliates, Copyright 2014-2015 Stripe, Inc",
// https://github.com/ccding/go-stun/blob/master/main.go#L1
"ccding/go-stun": "Copyright &copy; 2016 Cong Ding",
// https://github.com/search?q=repo%3Acertifi%2Fgocertifi%20copyright&type=code
// "certifi/gocertifi": "No copyrights found",
// https://github.com/search?q=repo%3Aebitengine%2Fpurego%20copyright&type=code
"ebitengine/purego": "Copyright &copy; 2022 The Ebitengine Authors",
// https://github.com/search?q=repo%3Agoogle%2Fpprof%20copyright&type=code
"google/pprof": "Copyright &copy; 2016 Google Inc",
// https://github.com/greatroar/blobloom/blob/master/README.md?plain=1#L74
"greatroar/blobloom": "Copyright &copy; 2020-2024 the Blobloom authors",
// https://github.com/jmespath/go-jmespath/blob/master/NOTICE#L2
"jmespath/go-jmespath": "Copyright &copy; 2015 James Saryerwinnie",
// https://github.com/maxmind/geoipupdate/blob/main/README.md?plain=1#L140
"maxmind/geoipupdate": "Copyright &copy; 2018-2024 by MaxMind, Inc",
// https://github.com/search?q=repo%3Apuzpuzpuz%2Fxsync%20copyright&type=code
// "puzpuzpuz/xsync": "No copyrights found",
// https://github.com/search?q=repo%3Atklauser%2Fnumcpus%20copyright&type=code
"tklauser/numcpus": "Copyright &copy; 2018-2024 Tobias Klauser",
// https://github.com/search?q=repo%3Auber-go%2Fmock%20copyright&type=code
"go.uber.org/mock": "Copyright &copy; 2010-2022 Google LLC",
}
var urlMap = map[string]string{
"fontawesome.io": "https://github.com/FortAwesome/Font-Awesome",
"go.uber.org/automaxprocs": "https://github.com/uber-go/automaxprocs",
"go.uber.org/mock": "https://github.com/uber-go/mock",
"google.golang.org/protobuf": "https://github.com/protocolbuffers/protobuf-go",
"gopkg.in/yaml.v2": "", // ignore, as gopkg.in/yaml.v3 supersedes
"gopkg.in/yaml.v3": "https://github.com/go-yaml/yaml",
"sigs.k8s.io/yaml": "https://github.com/kubernetes-sigs/yaml",
}
const htmlFile = "gui/default/syncthing/core/aboutModalView.html"
type Type int
const (
// TypeJS defines non-Go copyright notices
TypeJS Type = iota
// TypeKeep defines Go copyright notices for packages that are still used.
TypeKeep
// TypeToss defines Go copyright notices for packages that are no longer used.
TypeToss
// TypeNew defines Go copyright notices for new packages found via `go mod graph`.
TypeNew
)
type CopyrightNotice struct {
Type Type
Name string
HTML string
Module string
URL string
Copyright string
RepoURL string
RepoCopyrights []string
}
var copyrightRe = regexp.MustCompile(`(?s)id="copyright-notices">(.+?)</ul>`)
func main() {
bs := readAll(htmlFile)
matches := copyrightRe.FindStringSubmatch(string(bs))
if len(matches) <= 1 {
log.Fatal("Cannot find id copyright-notices in ", htmlFile)
}
modules := getModules()
notices := parseCopyrightNotices(matches[1])
old := len(notices)
// match up modules to notices
matched := map[string]bool{}
removes := 0
for i, notice := range notices {
if notice.Type == TypeJS {
continue
}
found := ""
for _, module := range modules {
if strings.Contains(module, notice.Name) {
found = module
break
}
}
if found != "" {
matched[found] = true
notices[i].Module = found
continue
}
removes++
fmt.Printf("Removing: %-40s %-55s %s\n", notice.Name, notice.URL, notice.Copyright)
notices[i].Type = TypeToss
}
// add new modules to notices
adds := 0
for _, module := range modules {
_, ok := matched[module]
if ok {
continue
}
adds++
notice := CopyrightNotice{}
notice.Name = module
if strings.HasPrefix(notice.Name, "github.com/") {
notice.Name = strings.ReplaceAll(notice.Name, "github.com/", "")
}
notice.Type = TypeNew
url, ok := urlMap[module]
if ok {
notice.URL = url
notice.RepoURL = url
} else {
notice.URL = "https://" + module
notice.RepoURL = "https://" + module
}
notices = append(notices, notice)
}
if removes == 0 && adds == 0 {
// authors.go is quiet, so let's be quiet too.
// fmt.Printf("No changes detected in %d modules and %d notices\n", len(modules), len(notices))
os.Exit(0)
}
// get copyrights via Github API for new modules
notfound := 0
for i, n := range notices {
if n.Type != TypeNew {
continue
}
copyright, ok := copyrightMap[n.Name]
if ok {
notices[i].Copyright = copyright
continue
}
notices[i].Copyright = defaultCopyright(n)
if strings.Contains(n.URL, "github.com/") {
notices[i].RepoURL = notices[i].URL
owner, repo := parseGitHubURL(n.URL)
licenseText := getLicenseText(owner, repo)
notices[i].RepoCopyrights = extractCopyrights(licenseText, n)
if len(notices[i].RepoCopyrights) > 0 {
notices[i].Copyright = notices[i].RepoCopyrights[0]
}
notices[i].HTML = fmt.Sprintf("<li><a href=\"%s\">%s</a>, %s.</li>", n.URL, n.Name, notices[i].Copyright)
if len(notices[i].RepoCopyrights) > 0 {
continue
}
}
fmt.Printf("Copyright not found: %-30s : using %q\n", n.Name, notices[i].Copyright)
notfound++
}
replacements := write(notices, bs)
fmt.Printf("Removed: %3d\n", removes)
fmt.Printf("Added: %3d\n", adds)
fmt.Printf("Copyrights not found: %3d\n", notfound)
fmt.Printf("Old package count: %3d\n", old)
fmt.Printf("New package count: %3d\n", replacements)
}
func write(notices []CopyrightNotice, bs []byte) int {
keys := make([]string, 0, len(notices))
noticeMap := make(map[string]CopyrightNotice, 0)
for _, n := range notices {
if n.Type != TypeKeep && n.Type != TypeNew {
continue
}
if n.Type == TypeNew {
fmt.Printf("Adding: %-40s %-55s %s\n", n.Name, n.URL, n.Copyright)
}
keys = append(keys, n.Name)
noticeMap[n.Name] = n
}
slices.Sort(keys)
indent := " "
replacements := []string{}
for _, n := range notices {
if n.Type != TypeJS {
continue
}
replacements = append(replacements, indent+n.HTML)
}
for _, k := range keys {
n := noticeMap[k]
line := fmt.Sprintf("%s<li><a href=\"%s\">%s</a>, %s.</li>", indent, n.URL, n.Name, n.Copyright)
replacements = append(replacements, line)
}
replacement := strings.Join(replacements, "\n")
bs = copyrightRe.ReplaceAll(bs, []byte("id=\"copyright-notices\">\n"+replacement+"\n </ul>"))
writeFile(htmlFile, string(bs))
return len(replacements)
}
func readAll(path string) []byte {
fd, err := os.Open(path)
if err != nil {
log.Fatal(err)
}
defer fd.Close()
bs, err := io.ReadAll(fd)
if err != nil {
log.Fatal(err)
}
return bs
}
func writeFile(path string, data string) {
err := os.WriteFile(path, []byte(data), 0o644)
if err != nil {
log.Fatal(err)
}
}
func getModules() []string {
cmd := exec.Command("go", "mod", "graph")
output, err := cmd.Output()
if err != nil {
log.Fatal(err)
}
seen := make(map[string]struct{})
scanner := bufio.NewScanner(bytes.NewReader(output))
for scanner.Scan() {
line := scanner.Text()
fields := strings.Fields(line)
if len(fields) == 0 {
continue
}
if !strings.HasPrefix(fields[0], "github.com/syncthing/syncthing") {
continue
}
// Get left-hand side of dependency pair (before '@')
mod := strings.SplitN(fields[1], "@", 2)[0]
// Keep only first 3 path components
parts := strings.Split(mod, "/")
if len(parts) == 1 {
continue
}
short := strings.Join(parts[:min(len(parts), 3)], "/")
if strings.HasPrefix(short, "golang.org/x") ||
strings.HasPrefix(short, "github.com/prometheus") ||
short == "go" {
continue
}
seen[short] = struct{}{}
}
adds := make([]string, 0)
for k := range seen {
adds = append(adds, k)
}
slices.Sort(adds)
return adds
}
func parseCopyrightNotices(input string) []CopyrightNotice {
doc, err := html.Parse(strings.NewReader("<ul>" + input + "</ul>"))
if err != nil {
log.Fatal(err)
}
var notices []CopyrightNotice
typ := TypeJS
var f func(*html.Node)
f = func(n *html.Node) {
if n.Type == html.ElementNode && n.Data == "li" {
var notice CopyrightNotice
var aFound bool
for c := n.FirstChild; c != nil; c = c.NextSibling {
if c.Type == html.ElementNode && c.Data == "a" {
aFound = true
for _, attr := range c.Attr {
if attr.Key == "href" {
notice.URL = attr.Val
}
}
if c.FirstChild != nil && c.FirstChild.Type == html.TextNode {
notice.Name = strings.TrimSpace(c.FirstChild.Data)
}
} else if c.Type == html.TextNode && aFound {
// Anything after <a> is considered the copyright
notice.Copyright = strings.TrimSpace(html.UnescapeString(c.Data))
notice.Copyright = strings.Trim(notice.Copyright, "., ")
}
if typ == TypeJS && strings.Contains(notice.URL, "AudriusButkevicius") {
typ = TypeKeep
}
notice.Type = typ
var buf strings.Builder
_ = html.Render(&buf, n)
notice.HTML = buf.String()
}
notice.Copyright = strings.ReplaceAll(notice.Copyright, "©", "&copy;")
notice.HTML = strings.ReplaceAll(notice.HTML, "©", "&copy;")
notices = append(notices, notice)
}
for c := n.FirstChild; c != nil; c = c.NextSibling {
f(c)
}
}
f(doc)
return notices
}
func parseGitHubURL(u string) (string, string) {
parsed, err := url.Parse(u)
if err != nil {
log.Fatal(err)
}
parts := strings.Split(strings.Trim(parsed.Path, "/"), "/")
if len(parts) < 2 {
log.Fatal(fmt.Errorf("invalid GitHub URL: %q", parsed.Path))
}
return parts[0], parts[1]
}
func getLicenseText(owner, repo string) string {
url := fmt.Sprintf("https://api.github.com/repos/%s/%s/license", owner, repo)
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Accept", "application/vnd.github.v3+json")
if token := os.Getenv("GITHUB_TOKEN"); token != "" {
req.Header.Set("Authorization", "Bearer "+token)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
var result struct {
Content string `json:"content"`
Encoding string `json:"encoding"`
}
body, _ := io.ReadAll(resp.Body)
err = json.Unmarshal(body, &result)
if err != nil {
log.Fatal(err)
}
if result.Encoding != "base64" {
log.Fatal(fmt.Sprintf("unexpected encoding: %s", result.Encoding))
}
decoded, err := base64.StdEncoding.DecodeString(result.Content)
if err != nil {
log.Fatal(err)
}
return string(decoded)
}
func extractCopyrights(license string, notice CopyrightNotice) []string {
lines := strings.Split(license, "\n")
re := regexp.MustCompile(`(?i)^\s*(copyright\s*(?:©|\(c\)|&copy;|19|20).*)$`)
copyrights := []string{}
for _, line := range lines {
if matches := re.FindStringSubmatch(strings.TrimSpace(line)); len(matches) == 2 {
copyright := strings.TrimSpace(matches[1])
re := regexp.MustCompile(`(?i)all rights reserved`)
copyright = re.ReplaceAllString(copyright, "")
copyright = strings.ReplaceAll(copyright, "©", "&copy;")
copyright = strings.ReplaceAll(copyright, "(C)", "&copy;")
copyright = strings.ReplaceAll(copyright, "(c)", "&copy;")
copyright = strings.Trim(copyright, "., ")
copyrights = append(copyrights, copyright)
}
}
if len(copyrights) > 0 {
return copyrights
}
return []string{}
}
func defaultCopyright(n CopyrightNotice) string {
year := time.Now().Format("2006")
return fmt.Sprintf("Copyright &copy; %v, the %s authors", year, n.Name)
}
func writeNotices(path string, notices []CopyrightNotice) {
s := ""
for i, n := range notices {
s += "# : " + strconv.Itoa(i) + "\n" + n.String()
}
writeFile(path, s)
}
func (n CopyrightNotice) String() string {
return fmt.Sprintf("Type : %v\nHTML : %v\nName : %v\nModule : %v\nURL : %v\nCopyright: %v\nRepoURL : %v\nRepoCopys: %v\n\n",
n.Type, n.HTML, n.Name, n.Module, n.URL, n.Copyright, n.RepoURL, strings.Join(n.RepoCopyrights, ","))
}
func (t Type) String() string {
switch t {
case TypeJS:
return "TypeJS"
case TypeKeep:
return "TypeKeep"
case TypeToss:
return "TypeToss"
case TypeNew:
return "TypeNew"
default:
return "unknown"
}
}