Anti-spoofing Techniques for GNSS Receivers

(Project in association with GNSS-SDR)


Global Navigation Satellite System (GNSS) is a primary source of precise positioning, navigation and timing information for a wide-variety of applications like navigation, autonomous vehicles, power-grids, communications, asset tracking and even financial systems. Importance of satellite navigation is ever increasing in safety and security-critical applications. GNSS is capable of providing a robust position, velocity and timing (PVT) solution. However, the lack of authentication in civilian navigation systems, leaves them vulnerable to signal spoofing attacks. In a signal spoofing attack, the attacker transmits specially crafted signals that can force the receiver to calculate a false PVT solution. These specially crafted signals imitate legitimate satellite signals and are powerful enough to overshadow legitimate satellite signals. In past years researchers have demonstrated the susceptibility of these systems to spoofing attacks. Most notable <1> where they were able to modify the course of a ship and <2> where the researchers were able to take over a UAV mid-flight. There are also reports of Global Positioning System (GPS) spoofing in the wild. Eg. <references>. Widespread availability of inexpensive COTS software-defined radios and open source software, GPS spoofing is possible with $100 worth of hardware.

In recent years researchers have proposed various mechanisms to counter GNSS spoofing attacks. The simple nature of GNSS makes it fundamentally challenging to develop security mechanisms that can provide PVT solution authenticity and integrity. The proposed countermeasures are cryptographic solutions, physical layer solutions or logical layer solutions. Each countermeasure solution is capable of providing anti-spoofing capabilities against a specific set of attacks. This GSOC project aims at implementing well-known physical and logical layer solutions in GNSS-SDR, an open-source software-defined receiver that provides signal processing software for multiple satellite navigation systems.

Find the repository here all the files mentioned in this document consider this repository as the base directory

Overview of anti-spoofing techniques:

This project focuses on three categories of anti-spoofing techniques to detect GNSS spoofing attacks.

Type 1: Multi-receiver spoofing detection

This technique incorporates multiple networked GNSS receivers. Spoofing detection techniques that involve multiple receivers require the development of additional infrastructure which is not available in GNSS-SDR. Hence, these techniques are deemed optional and the decision to implement these will be taken based on the implementation of other techniques.

Type 2: Physical layer checks

This type of checks involves checks based on the signal’s physical characteristics like the power level and cross-ambiguity function matrix  obtained in the acquisition process.

Power level check:

The power level check observes the prompt correlator output obtained from the tracking loops. This function checks for sudden changes to the prompt correlator value of the tracked signal. This correlator value corresponds to the baseband amplitude of the received signal. In a non-adversarial scenario (no spoofing) this value will not show sudden changes as the TX power of the satellites is constant. However, when an attacker executes an overshadow attack where the attacker’s signals are strong enough to overshadow the legitimate signals, the signal’s amplitude will show rapid changes.

Carrier-to-noise density ratio (C/No) check:

CNo is the ratio of the carrier power and the noise power density expressed in dB-Hz. This value determines whether the receiver can lock on the carrier and demodulate the signal to obtain transmitted data. Each receiver has a minimum CNo value set to determine the quality of the received signal. In case of satellite navigation CNo value is calculated for each visible satellite. In this check, the function compares the CNo values of all the signals received from all the satellites.CNo values of each individual satellite varies as a function of the relative range between the satellite and the receiver. However, if the signals have a common RF source, the C/No values are uniform. This is often the case in case of naive overshadow attacks. The most common way of generating spoofing signals is to use a GPS simulator with an RF frontend. A common RF frontend results in uniform CNo values. A comparison of CNo value can be used to detect such an overshadow attack.

Cross-ambiguity function matrix check:

The cross-ambiguity function (CAF) is the magnitude of the correlation between the received signal and the local replica of a specific satellite signal. Acquisition is a process of determining whether signal from a particular satellite is present in the received signal. In this process the receiver performs a circular cross-correlation operation in frequency and time domain. If this operation results in a correlation value (a peak) above a certain threshold, the signal is considered to be acquired. In a non-adversarial scenario, this process results in only a single[1] peak that crosses the threshold value. However, in case of a spoofing attack, there are multiple peaks that cross the threshold value as the attacker transmits signals that imitate legitimate satellite signals. These peaks are defined as auxiliary peaks and tracking such peaks can lead to spoofing detection. In the original work[2] It is defined as Auxiliary Peak Tracking. It is now re-implemented in GNSS-SDR as part of this project.

Type 3: Logical layer checks

Logical layer checks consist of model-based checks to determine outliers. These functions check the consistency of receiver observables and calculated PVT solutions with configurable threshold values.

Position Consistency:

In this type of check, the position consistency is verified by three techniques. Each technique is used in different scenarios.

  1. Static position check: The obtained position is compared with a predetermined surveyed position. If the obtained position is not in the proximity of the surveyed position a spoofing detection alarm is raised. This type of check is useful only in case of static receivers that act as markers or checkpoints.
  2. Position jumps: Position jumps are defined as rapid changes in the receiver’s position which are not consistent with the receiver’s velocity. In a spoofing attack, an attacker's signal can result in a rapid change in the receiver’s position which resembles a “jump”. This function checks for such jumps by comparing the distance between two consecutive positions.
  3. Velocity consistency: Velocity of the receiver can be estimated in the following ways: i) Doppler shift measurements, ii) differencing position estimates over time, iii) observing the carrier’s time domain properties and iv) changes in pseudorange measurements. RTKLIB, the library used to calculate the PVT solution in GNSS-SDR uses a combination of these techniques to estimate the velocity. Velocity consistency check uses these estimates to verify the consistency of the calculated position by comparing the proximity of a projected position to the obtained position.
  4. Abnormal position checks: Interference between legitimate signals and the attacker’s signals can cause the receiver to calculate abnormal location. Eg, the reported altitude and the ground speed of the receiver is beyond feasible values.

The receiver is configured to raise an alarm in case any of these checks fail.

Clock Consistency:

This model checks and examines the receiver clock drift and the calculated UTC time for normal behavior. The observables block in GNSS-SDR calculates clock offset and clock drift. In GNSS timing attacks, the attacker constructs the signals such that they drift significantly over time to force the receiver to calculate false timing information. The receiver is programmed to examine the variance of the drift and calculate clock offset error to verify the consistency of clock information. The function also compares the calculated UTC time with an external source to check if the timing solution is consistent i.e., if the timing solution is in the past, present or the future.        

Implementation strategy:

Spoofing Detection Methods

All the spoofing detection methods are defined in


Methods are implemented in


The configuration object that store all the spoofing detection parameters are defined as


class defined at:


Majority of the methods are called from the PVT block with exception of amplitude check and TOW check are called from the tracking block and the telemetry block respectively. Spoofing detector configuration parameters are set in the respective block’s adapter alongwith parameters of that particular block.

Spoofing Detection Report

The spoofing detection report can be obtained from the telecommand interface. For more details check out the GNSS-SDR documentation. Command to obtain the report is “spoofer_status”.



Definition: src/core/receiver/tcp_cmd_interface.h:72 

Implementation: src/core/receiver/

This method calls the get_spoofer_status() method defined in the PVT interface and implemented in the PVT block. This method requires a reference to a spoofer status struct.


Definition: src/core/interfaces/pvt_interface.h:70

Implementation: src/algorithms/PVT/gnuradio_blocks/

Call: src/core/receiver/


Definition: src/algorithms/libs/spoofing_detector.h:33

This struct stores the results of individual tests performed by the receiver.

Figure 1: Spoofing detection report obtained from telecommand interface

Type 1: Multi-receiver spoofing detection

This check is implemented independent of GNSS-SDR. All the functions are placed in


It connects to multiple instances of GNSS-SDR and receives PVT information. It treats multiple receivers as a single constellation and compares its geometry with a predetermined set of coordinates. It performs three types of checks

  1. Checks if received coordinates are unique

In case a spoofer unaware of such a setup tries to spoof, it will end up spoofing all the receivers to a single location and as a result all receivers will report the same location.

  1. Direct comparison with reference coordinates

In this technique the reference coordinates are propagated using the velocity vectors received from the receivers. It uses the propagate_coords() function to propagate the coordinates. It is followed by a proximity check where the propagated coordinates’ proximity to received coordinates is calculated by calculating the distance between the coordinates using the Haversine formula[3] It uses the function get_distance() to calculate the distance. If the distance crosses a set threshold, spoofing is detected.

  1. Geometrical comparison

Here, the perimeter and the area of the polygon formed by the received coordinates and the reference coordinates are compared. The tests allow an error of 1% by default. This can be configured as required.

Type 2:  Physical layer checks

Power level check:

This check compares the value of prompt correlator with a set threshold. This check is implemented at:


It is enabled by setting SecureGNSS.enable_amp_check=true

This function averages absolute prompt_I value and compares it with an adaptive average and it checks for sudden changes in the average which can occur only in case of a spoofing attack. C/No can also be used to detect such an attack, however, if the attacker is powerful enough to bury the legitimate signals under the noise floor, the C/No values will not be affected as it is a ratio of the carrier power and noise. Thus this test relies on the prompt_I value obtained from the tracking loops.

Figure 1: Prompt I correlator value showing jump in presence of a overshadow attack on PRN 16     (TRACE 4)

Carrier-to-noise density ratio (C/No) check:

This check calculates the standard deviation of C/No values of all the tracked satellites. The check_cno() method accepts a vector of C/No values obtained from the gnss_synchro object. This method is called from the PVT block.

Definition: src/algorithms/libs/spoofing_detector.h:134

Implementation: src/algorithms/libs/

Call: src/algorithms/PVT/gnuradio_blocks/

Cross-ambiguity function matrix check:

This check is enabled by the SecureGNSS.enable_apt flag in the configuration file. Each satellite is assigned multiple channels, this value can be configured through the SecureGNSS.channels_per_sv parameter in the configuration file. Each channel tracks a different peak as seen in the acquisition plot or the CAF matrix. Eg., if the receiver is configured to run 7 channels, if apt is enabled, gnss_flowgraph will initiate 7 x # of channels_per_sv. The first 7 channels will be primary channels and the rest will be auxiliary channels. Each channel object has a primary channel flag. If the primary channel flag is false there is a value which indicates the primary channel number. Similar changes are made to the gnss_synchro object so that other blocks from the flowgraph can identify primary and auxiliary channels. Similarly each channel is assigned a value that indicates which peak to track. /src/core/receiver/



Once channels are initiated, the acquisition block is responsible for allocating peaks to individual channels. If the enable_apt flag is true, the acquisition block will execute acquire_aux_peak() method.

Definition: src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.h:234

Implementation: src/algorithms/acquisition/gnuradio_blocks/

Call: src/algorithms/acquisition/gnuradio_blocks/

This method sorts the CAF matrix and assigns a peak based on the peak_to_track value of the channel. For details on this process refer to <code place>. By default the highest peak is assigned to the primary channel. A peak is assigned to an auxiliary channel only if the difference in code phase delays is above a predetermined value that can be configured by setting SecureGNSS.peak_separation=500. This value is in nanoseconds.

The tracking, telemetry and observables block don’t play a role in APT. However, the debug cout statements are suppressed if the channel is not a primary channel.

The final peak separation is calculated in the PVT block at <code place> using the tracking sample counter. The resolution of peak separation depends on the sampling rate. The spoofing flag is set accordingly. If spoofing is not detected, a stop_tracking message is sent to the control thread to reset the auxiliary channel and re-acquire auxiliary peaks. This is done to be able to detect seamless takeover attacks.

By default the PVT block will use the primary peaks to calculate the PVT solution. However, the receiver can be forced to use the auxiliary peaks to calculate the PVT solution. This can be done through the SecureGNSS.use_aux_peak parameter in the configuration file. Moreover, the user can switch between peaks at run time through the telecommand interface. switch_peaks() method is added to the PVT interface to enable the user to switch between auxiliary and primary peaks at runtime.


Definition: src/core/interfaces/pvt_interface.h:55

Implementation: src/algorithms/PVT/gnuradio_blocks/

Figure: (a) Shows presence of a single peak in a non-adversarial setting while (b) shows presence of auxiliary peaks in adversarial setting

Type 3:  Logical layer checks

Position Consistency:

All the position consistency check methods are called from the PVT block at <code place>. PVT block calls check_PVT_consistency() which executes rest of the consistency methods

Static position check:

Config params


Implementation:  src/algorithms/libs/

Call:  src/algorithms/libs/,228,236,238,295

Position jump check:

Maximum position jump param. This check compares the distance between consecutive position solutions and compares it with a set of propagated coordinates. This check relies on the last known good location (lkg) value. Every time a position solution passes the check, this value is updated. Future values are then compared with this lkg value.


Definition: src/algorithms/libs/spoofing_detector.h:224

Implementation: src/algorithms/libs/

Call: src/algorithms/libs/

Velocity consistency

Velocity estimates are used to propagate  (t - 1)th  coordinates. The propagated coordinates’ proximity to the (t)th coordinates is calculated. If the proximity check fails, (t)t estimate is considered to be inconsistent.


Definition: src/algorithms/libs/spoofing_detector.h:227

Implementation: src/algorithms/libs/

Call: src/algorithms/libs/,249


Definition: src/algorithms/libs/spoofing_detector.h:225

Implementation: src/algorithms/libs/

Call: src/algorithms/libs/

Abnormal position checks:

This method compares the calculated solution with a set of abnormal or infeasible values. These values can be set through the configuration file.






Definition: src/algorithms/libs/spoofing_detector.h:228

Implementation: src/algorithms/libs/

Call: src/algorithms/libs/

Figure: Comparison of X,Y and Z measurements in non-adversarial and adversarial settings. Spoofing can be observed at 50-60 s mark where the receiver jumps position (TRACE 1)

Clock Consistency:

Clock offset:

This method is implemented as implemented in the PNT-Integrity library[4] The method estimates the expected clock offset based on the previously received clock information by calculating the variance of previous clock values. The spoofing flag is raised if the error value crosses a threshold.


Definition: src/algorithms/libs/spoofing_detector.h:137

Implementation: src/algorithms/libs/

Call: src/algorithms/PVT/gnuradio_blocks/

Figure: A plot showing projected clock offset error over times (TRACE 4)

Clock jump:

Just like position jumps, this check detects jumps in the received TOW value. It compares 2 consecutive values TOW values with respective tracking sample counters. Any TOW manipulation attacks can be detected in such a way. This check also maintains a lkg value. Since this check is performed on each satellite, this check is performed in the telemetry block.


Definition: src/algorithms/libs/spoofing_detector.h:147

Implementation: src/algorithms/libs/

Call: src/algorithms/telemetry_decoder/gnuradio_blocks/

Check UTC time:

This check compares UTC time obtained from the host and the time calculated through GNSS. It notifies if the calculated time is in the past or future.


Definition: src/algorithms/libs/spoofing_detector.h:230

Implementation: src/algorithms/libs/

Call: src/algorithms/libs/


These checks are evaluated independently using a variety of GPS spoofing traces generated using open source GPS simulators[5] and TEXBAT[6] (a publicly available repository of GPS spoofing traces) For more information regarding TEXBAT checkout the documentation

*All the traces will be made available on request

Trace 1: overpowered_position_jump

This trace contains a naive GPS spoofing attack where there is no spoofing signal for the first 80 seconds after which the overpowered spoofing signal starts. The spoofing signal results in a position jump of 250 m.

Trace 2: overpowered_tow_jump

Similar to trace 1 but instead of position jump this trace contains TOW jump of 10 minutes

Trace 3: 3dB_power_advantage_position_separation

This trace simulates an ongoing seamless takeover attack where the attacker has managed to execute a seamless takeover attack and has deviated the receiver 500 m away from the original location.

Trace 4: TEXBAT Scenario 2 - Static overpowered time push

Refer to TEXBAT documentation for information.

Trace 5: TEXBAT Scenario 4 - Static matched power position push

Refer to TEXBAT documentation for information.

Trace 6: TEXBAT Scenario 5 - Dynamic overpowered time push

Refer to TEXBAT documentation for information.

Trace 7: TEXBAT Scenario 6-  Dynamic matched-power pos. Push

Refer to TEXBAT documentation for information.

[1] Multi-path transmissions are an exception

[2] Aanjhan Ranganathan, Hildur Ólafsdóttir, and Srdjan Capkun. 2016. SPREE: a spoofing resistant GPS receiver. In Proceedings of the 22nd Annual International Conference on Mobile Computing and Networking (MobiCom '16). Association for Computing Machinery, New York, NY, USA, 348–360. DOI: